0

ReScript seems to be a better way to write JS code, but I am not able to find what should be a simple single line of docs.

How do I call functions like document.createElement()?

I tried Js.document, Dom.document, by looking at this page: https://rescript-lang.org/docs/manual/latest/api, but that code gives an error in the playground:

The value document can't be found in Js
The value document can't be found in Dom

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132

3 Answers3

1

To call JS functions you'll need to use ReScript's JS interop. In this case, you can use the external keyword and @val/@scope attributes to get a ReScript function that will call document.createElement when invoked:

@val @scope(("window", "document"))
external createElement: string => unit = "createElement"

createElement("div")

This will be transformed to

window.document.createElement('div');

For quick prototyping, you can also just use external and interact with the objects like RS Objects directly:

@val external document: 'a = "document"

document["createElement"]("div")

Check out the interop cheatsheet and docs for external for more common patterns.

superhawk610
  • 2,457
  • 2
  • 18
  • 27
  • I followed the above advice of using `external`. I have correctly typed the return value of `createElement` as `Dom.element`, yet I am not able to access properties like outerHTML which are mentioned on Mozilla. Can you let me know what I am doing wrong? Code is [here](https://rescript-lang.org/try?code=AINwhgNgBMDODGB7ADgUwBToEQHcCWAdgCaI5YA0UWJ8ArgLaoEAuWAlGwFCoAezqAJwKQo8AajD8AohFSMWALiixmAwgHMoAXgB8UACKJ6AOlSz5zbVTETp5pq06dZlonhBWbk1DLkPsbiDsnIHGiLT8AgASACoAsgAynAD0yaEAZngCKgDCABZ4EEQpae7GKgCesk5AA). – vinay-deshmukh May 21 '21 at 03:16
  • ReScript provides the `Dom` module as a common set of opaque types for low-level UI libraries to work with; like it says on [the docs](https://rescript-lang.org/docs/manual/latest/api/dom), they don't provide any actual functionality. If you'd like to interact imperatively with the DOM, you'll need to write most of the actual code in JS and then expose a few entrypoints for ReScript (that's what the `Dom` opaque types are for, to make sure your RS code passes the expected value types). As @mr-polywhirl mentioned, the path of least resistance is to use an existing lib like React. – superhawk610 May 21 '21 at 05:05
  • 2
    @vinay-deshmukh , you will need to understand several different concepts before you can understand what you are doing wrong here. Stack Overflow is not a great place to have that discussion. I highly recommend asking this question on the ReScript forum, where people can have an extended discussion: https://forum.rescript-lang.org/ . Finally, if you just want to start using something immediately, try https://github.com/reasonml-community/bs-webapi-incubator – Yawar May 22 '21 at 03:48
1

you can use bs-webapi

open Webapi.Dom
open Belt

document
->Document.asHtmlDocument
->Option.flatMap(document => document->HtmlDocument.body)
->Option.map(body => {
  let root = document->Document.createElement("div", _)
  root->Element.setId("app")
  root->Element.appendChild(body)
})
->ignore

Arbaaz
  • 11
  • 3
-1

Since re-script is powered by React (JSX) and not standard ECMA JavaScript, I do not think you can use calls like document.createElement.

Instead, you should create the element via:

let element = <h1> {React.string("Hello World")} </h1>

This transpiles into the following:

var element = React.createElement("h1", undefined, "Hello World");

I modified the default Playground script:

module Button = {
  @react.component
  let make = (~count: int) => {
    let times = switch count {
    | 1 => "once"
    | 2 => "twice"
    | n => Belt.Int.toString(n) ++ " times"
    }
    let msg = "Click me " ++ times
    let element = <button> {React.string(msg)} </button>
    element
  }
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • 1
    React.createElement is not equivalent or even close to document.createElement. As I had mentioned, I am trying to use ReScript in JS, and not in a React project. – vinay-deshmukh May 21 '21 at 02:31