@Jens
Yes but I thought it was just a convenient way to define the formatter for both cases at the same time:
- single value slider
- range slider
But since in my code, Slider and RangeSlider are 2 different classes, I thought I could be more specific and define only the appropriate formatter for each case.
But @Colin is right! Even in the case of a Range slider, sometime the library calls the formatter function with a single value (I have no idea why, it does not make sense to me but anyway).
So I've change my FormatterCallback as follow (thanks @Colin)
@JsFunction
@FunctionalInterface
public interface FormatterCallback {
/**
* Returns the formatted tool-tip text to be displayed.
*
* @param value the slider value
* @return the formatted tool-tip text to be displayed.
*/
String formatTooltip(Any value);
}
@FunctionalInterface
public interface FormatterCallback {
/**
* Returns the formatted tool-tip text to be displayed.
*
* @param value the slider value
* @return the formatted tool-tip text to be displayed.
*/
String formatTooltip(Any value);
}
and define then like that :
formatterExample.setFormatter(any -> {
if (any instanceof JsNumber) {
return "Current value: " + any.asDouble();
}
return null;
});
rangeFormatterExample.setFormatter(any -> {
if (any instanceof Range) {
Range range = (Range) any;
return "Range: [" + range.getMinValue() + ", " + range.getMaxValue() + "]";
}
return null;
});
if (any instanceof JsNumber) {
return "Current value: " + any.asDouble();
}
return null;
});
rangeFormatterExample.setFormatter(any -> {
if (any instanceof Range) {
Range range = (Range) any;
return "Range: [" + range.getMinValue() + ", " + range.getMaxValue() + "]";
}
return null;
});
Le samedi 25 octobre 2025 à 22:30:46 UTC+8, Jens a écrit :
The default formatter in bootstrap-slider looks likeformatter: function(val) {if (Array.isArray(val)) {return val[0] + " : " + val[1];} else {return val;}}IMHO a strong indication that you must use Any or Object and the formatter then needs to check how to format the input. Only if you can guarantee that the component will always call the function with an array you can use a <Range> generic.-- J.Colin Alworth schrieb am Freitag, 24. Oktober 2025 um 17:06:40 UTC+2:Switching to manual testing in your pom lets me run the test in a real browser, with breakpoints enabled.diff --git a/pom.xml b/pom.xml
index 39c43269..58bd6671 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,6 +108,10 @@
<inherited>true</inherited>
<configuration>
<sourceLevel>1.8</sourceLevel>
+ <testArgs>
+ <arg>-runStyle</arg>
+ <arg>Manual:1</arg>
+ </testArgs>
</configuration>
</plugin>
</plugins>The emulated stack trace experience isn't very much fun, but after a time it is possible to see that the function is being called with an array, [5, 10] from inside bootstrap itself - but the bootstrap code specifically shows that it is only passing the 0th element, as this._state.value[0].In order to call the Java lambda with its generic arg, GWT inserts a typecheck for generics. Range is declared as "actually this is an Array", so GWT emulates that check with Array.isArray:Zz(($B = (ZB[b] = iD + oD,
a) == null || (ZB[b] = iD + pD,
Array).isArray(($B = (ZB[b] = iD + oD,
a),Again, this is nasty to read because of emulated stack traces - but 5 clearly fails that check.I then added a `debugger` statement to the JSNI function, to see if it saw the same thing - it was actually called several times, first with 5, then 10, before finally the expected [1,2] array. When it received 5 and 10, the result returned was the useless string "Range: [undefined,undefined]".Is it wrong for GWT to check the types here? It is causing you a headache for sure, but the lambda is clearly nonsense if you get a number instead of a range array. You could take something like Any or Object as the param and typecheck it, or maybe there's a different way to use bootstrap here to get the result you expect?On Wednesday, October 22, 2025 at 3:39:28 AM UTC-5 freddy....@gmail.com wrote:Hello,I'm working on updating/migrating the gwtbootstrap3 library
- updating all external Javascript libraries
- migrating to JsInterop (get rid of jsni)
- migrating to Bootstrap 5
But I'm facing an issue with the following @JsFunctionimport jsinterop.annotations.JsFunction;
@JsFunction
@FunctionalInterface
public interface FormatterCallback<T> {
String formatTooltip(T value);
}When I declare it with lambda it fails// using @JsFunction
slider.setFormatter(range -> "Range: [" + range.getAt(0) + "," + range.getAt(1) + "]");But if I declare it with JSNI it worksslider.setFormatter(rangeFormatter());private native FormatterCallback<Range> rangeFormatter() /*-{
return function (value) {
return "Range: [" + value[0] + "," + value[1] + "]";
};
}-*/;You can find the successful and the failing GWTTestCase here:And of course the full projet https://github.com/freddyboucher/gwtbootstrap3.gitWhen I log in the console the 2 functions it looks like that===JSNI===
ƒ (value_0_g$){
return 'Range: [' + value_0_g$[0] + ', ' + value_0_g$[1] + ']';
}===JsFunction===
ƒ (){
return samMethod_0_g$.apply(lambda_0_g$, arguments);
}Any idea how to resolve it?
thanks
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/google-web-toolkit/65394e97-3b9a-4edb-a578-6872c6fa0d25n%40googlegroups.com.
No comments:
Post a Comment