我们需要在应用程序中支持某些数字(利率)的高精度,但我们仍然希望默认情况下将它们四舍五入到小数点后4位。
因此,在表中,某些单元格包含TextField<BigDecimal>
中的速率,用户可以在其中输入任何精度的值,但显示带有4个小数点的值。这是通过自定义BigDecimal转换器(as documented in this answer)完成的。
我们还有一个简单的工具提示(标题属性),显示确切的值(当我说“确切”时,当然有一些规模的上限,目前为16):
这些字段具有“onblur”AjaxFormComponentUpdatingBehavior,这会导致更改的值立即保存并更新表的其余部分。
现在,有两个问题:
作为#1的hacky修复,我更改了底层DTO的setter,以便在传入的新值相同但规模较小的情况下,它实际上不会更改值。但是我正在寻找能够解决#2的问题(它会自动处理#1)。
final TextField<BigDecimal> field;
BigDecimal interestRate = ...; // current exact value from the model object
field.add(new AjaxFormComponentUpdatingBehavior("onfocus") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
// something I could do here? using e.g.
// field.setModelObject(), field.setConvertedInput()
// or field.getConverter(BigDecimal.class);
}
}
拥有字段,域对象&amp;上面代码中的确切BigDecimal值(在表的每次更新时执行),我可以做什么来替换UI中可见(可编辑)的值?
当字段聚焦时,我可以以某种方式交换转换器吗?转换器没有setter,但是可能会创建一个自定义的TextField子类,允许你动态更改转换器......?
作为最后的手段,我们可以更改转换器(增加setMaximumFractionDigits),以便始终显示确切的值(但这不是这个特定问题的解决方案,它只是回避它)。
答案 0 :(得分:0)
好吧,我最终得到了它。不是使用纯粹的Wicket,而是使用一个小的JavaScript hack。
正如问题所述,我已经在该字段的title
属性中得到了确切的值。所以我可以将属性值复制为输入字段的值。
<强>爪哇强>:
对于这些类型的TextField,添加一个调用JS函数的Behavior。这里的基本方法是getMarkupId()
,它返回我可以在JS中使用的(任意的,动态的)<input>
元素ID。
private void addPreservePrecisionBehavior(final TextField<BigDecimal> field) {
field.add(new AjaxFormComponentUpdatingBehavior("onclick") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
String js = String.format("copyExactValueFromTitle('%s')", field.getMarkupId());
target.appendJavascript(js);
}
});
}
JavaScript (在相关Wicket页面上加载的.js文件中):
/**
* Takes the specified input field's title and sets it as the field's value.
*
* @param elementId ID of an input element
*/
function copyExactValueFromTitle(elementId) {
if (!elementId) {
return;
}
var input = $('#' + elementId);
var exactValue = input.attr("title");
if (exactValue) {
input.val(exactValue);
}
}
(请注意,上面使用了jQuery;当然也可以在没有它的情况下使用它。)
唯一的问题,至少在我们的情况下,在调用onUpdate()
方法之前会有轻微的延迟(可能是200-500毫秒),这使得编辑字段成为不太顺利。 (如果用户快速更改了值,则JS代码会覆盖该更改。)
为了减少这种烦恼,我只在真正需要时添加行为:
if (interestRate != null && interestRate.stripTrailingZeros().scale() > 4) {
addPreservePrecisionBehavior(field);
}
随意发布更好的解决方案!
答案 1 :(得分:0)
我知道现在为时已晚,但为何不使用两个组件?
组件1显示舍入值,工具提示显示精确值。当您单击它时,它会隐藏自身并显示另一个组件,这是一个标准文本字段,其行为onblur
会隐藏组件2并再次显示组件1.