我们需要在应用程序中支持某些数字(利率)的高精度,但我们仍然希望在默认情况下将它们显示为四舍五入到小数点后 4 位。
因此,在表格中,一些单元格包含 TextField<BigDecimal>
中的比率用户可以在其中输入任意精度的值,但显示的值带有 4 个小数点。这是通过自定义 BigDecimal 转换器 ( as documented in this answer ) 完成的。
我们还有一个简单的工具提示(title 属性),显示精确值(当我说“精确”时,当然有一些比例上限,目前为 16):
这些字段具有“onblur”AjaxFormComponentUpdatingBehavior,这会导致立即保存更改的值并更新表的其余部分。
现在,有两个问题:
- 如果用户点击该字段,然后点击其他地方,四舍五入(4 decimal) 值在域对象中更新并在没有 用户甚至意识到她改变了任何东西。即,确切的值丢失了。
- 有点棘手:我想让编辑准确的值变得容易。 即,单击(聚焦)文本字段时,它应更改为 显示确切的值,以便用户可以轻松编辑该值(而不是 四舍五入的值(value))。
作为对 #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);
}
}
有了上面代码中的字段、域对象和确切的 BigDecimal 值(在每次更新表时执行),我该怎么做才能替换 UI 中可见(可编辑)的值强>?
当场聚焦时,我能否以某种方式交换转换器?转换器没有 setter ,但也许可以创建一个自定义 TextField 子类,允许您即时更改转换器...?
作为最后的手段,我们可以更改转换器(增加 setMaximumFractionDigits)以便始终显示准确的值(但这不是解决这个特定问题的方法,它只是回避它)。
最佳答案
好吧,我最终成功了。不使用纯 Wicket,而是使用一个小的 JavaScript hack。
如问题中所述,我已经在 title
中获得了准确的值字段的属性。所以我可以只复制属性值作为输入字段的值。
Java:
对于这些类型的 TextFields,添加一个调用 JS 函数的 Behavior。这里的基本方法是 getMarkupId()
它返回(任意的,动态的)<input>
我可以在 JS 中使用的元素 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);
}
随时发布更好的解决方案!
关于java - Wicket TextField<BigDecimal> 默认显示 4 位小数,但允许(轻松)编辑精确值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8836085/