Say I have the following html:
<div class="item">one</div>
<div class="item">two</div>
<div class="item">three</div>
I would like to log the innerHTML for each element. I have tried the following:
document
|> Document.querySelectorAll(".item")
|> NodeList.toArray /* not sure if this is needed */
|> Array.map(Document.ofNode) /* not sure if this is needed */
|> Array.map(Element.innerHTML)
|> Array.iter((number) => {
Js.log(number);
});
The error is on line |> Array.map(Element.innerHTML)
And the error is:
This has type:
array(Webapi.Dom.Element.t) => array(string)
But somewhere wanted:
array(Dom.node) => 'a
How can I use the Dom.node
so that I access the innerHTML
?
Document.ofNode
should be Element.ofNode
, but the error message indicates that this line isn't present at all in the code producing the error. ofNode
also returns an option
, since not all nodes are elements, so you have to unwrap that as well. Something like this should work:
document
|> Document.querySelectorAll(".item")
|> NodeList.toArray
|> Array.map(Element.ofNode)
|> Array.map(Js.Option.getExn)
|> Array.map(Element.innerHTML)
|> Array.iter(Js.log);
Or to avoid a bit of unnecessary array allocation and mapping:
document
|> Document.querySelectorAll(".item")
|> NodeList.toArray
|> Array.iter(node =>
node
|> Element.ofNode
|> Js.Option.getExn
|> Element.innerHTML
|> Js.log
);
It also has to be said that direct DOM manipulation isn't a great fit for Reason, or any statically typed functional language for that matter, since the DOM is inherently a very dynamically typed and object-oriented API. NodeList.toArray
, for example, is required because a NodeList
is not an array but an "array-like", which supports only a few array operations.