I wanted to implement an interactive slider using ReScript, so I wanted to translate this JavaScript to ReScript (courtesy: https://www.w3schools.com/howto/howto_js_rangeslider.asp):
var slider = document.getElementById("myRange");
var output = document.getElementById("demo");
output.innerHTML = slider.value; // Display the default slider value
// Update the current slider value (each time you drag the slider handle)
slider.oninput = function() {
output.innerHTML = this.value;
}
where the target HTML (slider.html
) is:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.slidecontainer {
width: 100%;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 25px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
background: #04AA6D;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
background: #04AA6D;
cursor: pointer;
}
</style>
</head>
<body>
<div class="slidecontainer">
<input type="range" min="1" max="100" value="50" class="slider" id="myRange">
<p>Value: <span id="demo"></span></p>
</div>
<script src="./bundled.bs.js"></script>
</body>
</html>
where the bundled.bs.js
is a result of bundling the compiled .bs.js
code with Browerify
.
So far, I have the following piece of code written using the rescript-webapi:
open Webapi.Dom
open Belt.Option
@val external document: Document.t = "document"
let slider = getExn(Document.getElementById("myRange", document))
let output = getExn(Document.getElementById("demo", document))
Element.setInnerText(output, getExn(Element.getAttribute("value", slider)))
Element.addEventListener("value", _ =>
Element.setInnerHTML(output, getExn(Element.getAttribute("value", slider))), slider)
However, this does not work as intended; I can see the slider and slide it around, but the input tag's value does not get updated:
What is missing from my ReScript translation?
+Update:
@glennsl has provided me with this code below:
open Webapi.Dom
open Belt
let slider = document->Document.getElementById("myRange")->Option.getExn
let output = document->Document.getElementById("demo")->Option.getExn
output->Element.setInnerText(slider->Element.getAttribute("value")->Option.getExn)
slider->Element.addEventListener("input", _ => {
let value = slider->Element.getAttribute("value")->Option.getExn
output->Element.setInnerHTML(value)
})
I can see the Value:
with the correct initial value, 50
.
However, even if I repositioned the slider, the value does not get updated:
As mentioned above, I compiled this code (dubbed slider.res
) into slider.bs.js
and bundled it with browserify slider.bs.js -o bundled.bs.js
.
Ugh, the main problem was twofold:
As @glennsl pointed out, the event name was wrong. It should be "input"
, not "value"
.
I mistook the this.value
to refer to the value
attribute of this
, which is slider
. Actually, this is considering slider
to be an HTML input element, and referring to its input value.
As we cannot directly cast an Dom.Element.t
to an Dom.HtmlInputElement.t
, we first convert this to Dom.Node.t
and then to Dom.HtmlInputElement.t
. So, building upon @glennsl's code, the code is:
open Webapi.Dom
open Belt
let slider = document->Document.getElementById("myRange")->Option.getExn
let output = document->Document.getElementById("demo")->Option.getExn
output->Element.setInnerText(slider->Element.getAttribute("value")->Option.getExn)
slider->Element.addEventListener("input", _ => {
let value = slider->Element.asNode->HtmlInputElement.ofNode->Option.getExn->HtmlInputElement.value
output->Element.setInnerHTML(value)
})