is there any way to format number in ZK label component that looks like like
<label value="${each.value}" /> ? Values are doubles and I want to separate thousands etc... I know that doublebox for example has format property but what if I just want to display number as label? Thanks for any help.
Feature Request
First of all I have opened a feature request for this on ZK's tracking system you can find it here. Please follow this if you want updates.
Ways of implementing
There are in fact ways of implementing this depending on what pattern & techniques you are using.
MVC & EL
You can create an EL function which will do the formatting for you in your ZUL file. First of all create a class such as this:
public class FormatElNumber {
public static String formatStock(double stock) {
final NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);
return nf.format(stock);
}
}
This will output numbers with two decimal places. Secondly you need to add this to the top of your zul file:
<?xel-method prefix="c" name="formatStock" class="demo.grid.hierarchy.FormatElNumber"
signature="java.lang.String formatStock(double)"?>
Then when you have a label you can do as follows:
<label style="color:red;" value="${c:formatStock(each.averageHigh)}" />
More infomration on this technique is available here.
MVVM
The MVVM is actually easier to implement, you create what's called a Converter, for example (please note this class is untested, but you get the idea).
public class NumberFormatConverter implements Converter {
#Override
public Object coerceToBean(Object val, Component comp, BindContext ctx) {
return null;
}
#Override
public Object coerceToUi(Object val, Component comp, BindContext ctx) {
if(!(val instanceof Integer)) {
throw new IllegalArgumentException("The argument must be a number!");
}
final Object tmp = ctx.getConverterArg("length");
int length = 0;
if(tmp instanceof Integer) {
length = (Integer)tmp;
}
final NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(length);
return nf.format(val);
}
}
Then all you do in your zul file is specify you would like to use a converter on the value, for example:
<label value="#load(vm.message) #converter(vm.myConverter)"/>
For more information on this technique you can refer here.
From the docs: http://books.zkoss.org/wiki/ZUML_Reference/EL_Expressions/Core_Methods/formatNumber
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<zk>
<label value="${c:formatNumber(2332315231, '$ ###,###,###.00')}" />
</zk>
Related
I have a selectbox and want to load the value and text into the template, similar to an HTML dropdown box. I am using ZK framework with Java on the back end.
<selectbox id="buListbox" model="${$composer.buModel}" >
<template name="model">
<label value="${each}" />
</template>
</selectbox>
When using ZK, you don't need the value to identify the selected object like in HTML.
When using the MVC pattern, binding a model via model attribute, the selected item is also stored in that model and can be retrieved in java via model.getSelection().
Furthermore, a model is not restricted to lists of String, but it can hold any object type you want. In the template section, you can display any property of that object. Then the properties' toString() method is used to get the value which is displayed. This also applies to ${each} itself.
Example:
Assuming your model is a ListModelList of type ValueType:
public class ValueType {
private String value;
private String text;
public ValueType(String value, String text) {
this.value=value;
this.text=text;
}
public String getText() {
return this.text;
}
public String getValue() {
return this.value;
}
}
private ListModelList<ValueType> typesModel;
public ListModelList<ValueType> getTypesModel() {
return typesModel;
}
You than can use the selectbox's model/template to display it's text property:
<selectbox id="typesSelectbox" model="${$composer.typesModel}">
<template name="model">
${each.text}
</template>
</selectbox>
In java, you then get the selected item via typeModel.getSelection() .
Here you can find a working ZKFiddle example.
I would like my uiBinder to use a ClientBundle which will provide some runtime customized labels. Kind of a TextResource but not from a text file !
I tried with GwtCreateResource but from the DevGuide it seems like it's not possible. Am I right ? (create() and name() are the only methods available)
What I would like to achieve is something like this:
client bundle:
public interface MyWidgetResources extends ClientBundle {
GwtCreateResource<WidgetLabels> labels();
#Source("lol.css")
CssResource style();
}
labels class:
public final class MyWidgetLabels {
public String title() {
return load("mywidget-title");
}
public String banner() {
return load("mywidget-banner");
}
private String load(String key) {
// load from external..
}
}
uiBinder:
<ui:with type="com.package.MyWidgetResources" field="res"/>
<gwt:SimplePanel>
<gwt:Label text="{res.labels.title}"></gwt:Label>
<gwt:Label text="{res.labels.banner}"></gwt:Label>
</gwt:SimplePanel>
My code looks like this already but res.label.title does not work because GwtCreateResource can only serve as class instantiator (res.labels.create().title()).
Is there a solution for me ? Maybe with a custom ResourceGenerator ?
As long as MyWidgetLabels can be created by GWT.create, you can put anything you want into that type, and you can make it behave however you'd like. You will need the create reference in your uibinder as you suggested at the end of the post to actually build the object, so your lines will look about like this:
<gwt:Label text="{res.labels.create.title}"></gwt:Label>
Each . separated piece (except the first, which is a ui:field/#UiField) is a no-arg method to be called - you declared labels() in MyWidgetResources, create() already existed in GwtCreateResource, and you created title() in your own MyWidgetLabels type.
Since that first piece is a ui:field/#UiField, you could have another that references res.labels.create as something like labels so that later you could instead say:
<gwt:Label text="{labels.title}"></gwt:Label>
Finally, yes, you could build your own ResourceGenerator which would enable you to do whatever you wanted to emit the type in question, as long as you extended the ResourcePrototype type and had a getName() method.
I have a rather complex form in the way that the number of form fields is flexibel. In short, the model object is a TLabel (TranslationLabel) that contains a Map of values (translations). Language here is an enum so the idea is that the number of fields (text areas) for which a translation is given depends on the values in this enum.
This is my form (simplified):
public class TranslationEditForm extends Form {
private final static List<Language> LANGUAGES = newArrayList(Language.values());
public TranslationEditForm(String id, final TranslationLabelView label) {
super(id, new CompoundPropertyModel<TranslationLabelView>(label));
ListView<Language> textAreas = new ListView<Language>("translationRepeater", LANGUAGES) {
#Override
protected void populateItem(final ListItem<Language> itemLang) {
//loop through the languages and create 1 textarea per language
itemLang.add(new Label("language", itemLang.getModelObject().toString()));
Model<String> textModel = new Model<String>() {
#Override
public String getObject() {
//return the value for current language
return label.getValue(itemLang.getModelObject());
}
#Override
public void setObject(String object) {
//set the value for current language
label.getTranslations().put(itemLang.getModelObject(), object);
}
};
itemLang.add(new TextArea<String>("value", textModel).setRequired(true));
}
};
//add the repeater containing a textarea per language to the form
this.add(textAreas);
}
}
Now, it works fine, 1 text area is created per language and its value is also set nicely; even more when changed the model gets updated as intended.
If you submit the form after emptying a text area (so originally there was a value) then of course there is a validation error (required). Normal (wicket) behaviour would be that the invalid field is still empty but for some reason the original value is reset and I don't understand why.
If I override onError like this:
#Override
protected void onError() {
this.updateFormComponentModels();
}
then it is fine, the value of the field is set to the submitted value (empty) instead of the original value.
Any idea what is causing this? What is wicket failing to do because the way I've set up the form (because with a simple form/model this is working fine as are the wicket examples)?
Posted as answer, so the question can be marked as solved:
ListView does recreate all its items at render time. This means that the validation will be broken. Have a look at API doc of the ListView
Calling setReuseItems() on the ListView solves this.
Regards,
Bert
I'm trying to find a way to automatically convert links in a panel to hyper-links. So for example a user input is:
"And here you can find my awesome example: http://example.com"
Is it possible in wicket to add an anchor element to each "http://..." text, so the above example would output
"And here you can find my awesome example: http://example.com"
instead?
You can use Wicket's built in SmartLinkLabel.
From the Javadoc:
If you have email addresses or web URLs in the data that you are displaying, then you can automatically display those pieces of data as hyperlinks, you will not have to take any action to convert that data.
One way to do this is to extend Label and override onComponentTagBody
Something like:
public class AnchorizeLabel extends Label {
public AnchorizeLabel(String id, String body) {
super(id, body);
}
#Override
protected void onComponentTagBody(MarkupStream stream, ComponentTag tag) {
String newBody = createAnchors(getDefaultModelObjectAsString());
replaceComponentTagBody(stream, tag, newBody);
}
private String createAnchors(String body) {
// regex magic to create links
}
}
You can also accomplish this with a custom IModel or IConverter but I prefer the Label approach.
I have a code template with a variable and I would like to capitalize(just the first letter) the value of this variable only in some occurrences. Is there a way to do this?
The template code is as follows - I would like to capitalize Property Name in my function names...
private $$${PropertyName};
${cursor}
public function get${PropertyName}()
{
return $$this->${PropertyName};
}
public function set${PropertyName}($$value)
{
$$this->${PropertyName} = $$value;
}
Please Note: This is a template for use with code templates in the IDE (not in PHP). For details see: http://www.ibm.com/developerworks/opensource/tutorials/os-eclipse-code-templates/index.html
I also want this and tried to build a custom TemplateVariableResolver to do it. (I already have one custom resolver in place that generates new UUIDs a la http://dev.eclipse.org/blogs/jdtui/2007/12/04/text-templates-2/.)
I made a custom resolver bound to capitalize:
public class CapitalizingVariableResolver extends TemplateVariableResolver {
#Override
public void resolve(TemplateVariable variable, TemplateContext context) {
#SuppressWarnings("unchecked")
final List<String> params = variable.getVariableType().getParams();
if (params.isEmpty())
return;
final String currentValue = context.getVariable(params.get(0));
if (currentValue == null || currentValue.length() == 0)
return;
variable.setValue(currentValue.substring(0, 1).toUpperCase() + currentValue.substring(1));
}
}
(plugin.xml:)
<extension point="org.eclipse.ui.editors.templates">
<resolver
class="com.foo.CapitalizingVariableResolver"
contextTypeId="java"
description="Resolves to the value of the variable named by the first argument, but with its first letter capitalized."
name="capitalized"
type="capitalize">
</resolver>
</extension>
that I would use like this: (I am working in Java; I see that you do not appear to be)
public PropertyAccessor<${propertyType}> ${property:field}() {
return ${property};
}
public ${propertyType} get${capitalizedProperty:capitalize(property)}() {
return ${property}.get();
}
public void set${capitalizedProperty}(${propertyType} ${property}) {
this.${property}.set(${property});
}
As of Eclipse 3.5, the problem I am having is that my custom resolver does not get a chance to re-resolve once I've specified a value for the property variable. It appears that the Java Development Tools (Eclipse JDT) do this dependent template variable re-resolution via a mechanism called MultiVariableGuess within the JavaContext (see addDependency()). Unfortunately for us, that mechanism does not seem to be exposed, so I/we can't use it to do the same (without lots of copy-and-paste or other redundant work).
At this point, I am giving up again for a while and will keep typing the leading-lowercase and leading-uppercase names separately into two independent template variables.