Oh I see !!
@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
[image: Screenshot 2025-10-27 at 09.37.57.png]
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);
}
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;
});
Le samedi 25 octobre 2025 à 22:30:46 UTC+8, Jens a écrit :
> The default formatter in bootstrap-slider looks like
>
> formatter: 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 [email protected]
>> 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 @JsFunction
>>>
>>> import 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 works
>>> slider.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:
>>>
>>> https://github.com/freddyboucher/gwtbootstrap3/blob/master/gwtbootstrap3-extras/src/test/java/org/gwtbootstrap3/extras/slider/client/ui/RangeSliderTest.java
>>>
>>> <http://RangeSliderTest.java>
>>>
>>> And of course the full projet
>>> https://github.com/freddyboucher/gwtbootstrap3.git
>>>
>>> When 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 [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/google-web-toolkit/65394e97-3b9a-4edb-a578-6872c6fa0d25n%40googlegroups.com.