Search code examples
domreasonbucklescript

Selecting elements from the DOM - Reasonml/BuckleScript querySelector


How would you select items from the DOM using Reason. I'm using bs-webapi for the DOM bindings here is what I want to do:

let parent = document |> Document.querySelector(".parent");
let child = Element.querySelector(".child", parent);

However, BuckleScript complains because parent isn't of the right type. It says parent is of type option(Dom.element) and parent is expected to be Dom.element.t. I'm new to Reason and trying to learn. I don't understand what option(Dom.element) means or how to make something like the above code block work. Any help is greatly appreciated


Solution

  • You need to unwrap the option variant, and we can do that with a switch and use the built-in None/Some variants.

    You can find some documentation on the option variant here: https://reasonml.github.io/docs/en/newcomer-examples.html#using-the-option-type

    Here is some more documentation on option: https://reasonml.github.io/docs/en/variant.html#option

    To do this, you would change your code to something like this:

    let parent = document |> Document.querySelector(".parent");
    let child = switch (parent) {
      | Some(p) => switch (Element.querySelector(".child", p)) {
        | Some(c) => c
        | None => raise(Failure("Unable to find child selector"))
      }
      | None => raise(Failure("Unable to find parent selector"))
    };
    

    If you wanted to instead log to the console instead of fail, you would need to return a valid Dom.element.t, which could be something like this:

    let emptyEl = document |> Document.createElement("noscript");
    let parent = document |> Document.querySelector(".parent");
    let child = switch (parent) {
      | Some(p) => switch (Element.querySelector(".child", p)) {
        | Some(c) => c
        | None => {
          Js.log("Unable to find child selector");
          emptyEl;
        }
      }
      | None => {
        Js.log("Unable to find parent selector");
        emptyEl;
      }
    };
    

    You would then want to check if your child element was a noscript to see if you found the child you were looking for.