Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

How to use HtmlInputElement (focus, select) ? #205

Open
Qziem opened this issue Oct 6, 2020 · 5 comments
Open

How to use HtmlInputElement (focus, select) ? #205

Qziem opened this issue Oct 6, 2020 · 5 comments

Comments

@Qziem
Copy link

Qziem commented Oct 6, 2020

I want to do simple thing. Just focus and select input field after click button. I have code like this:

[@react.component]
let make = () => {
  let inputRef = React.useRef(Js.Nullable.null);

  let handleSelect = _event => {
    let element =
      inputRef.current->Js.toOption->Belt.Option.flatMap(Webapi.Dom.HtmlInputElement.ofElement);

    switch (element) {
    | Some(input) =>
      Webapi.Dom.HtmlInputElement.focus(input);
      Webapi.Dom.HtmlInputElement.select(input);
    | None => ()
    };
  };

  <>
    <input
      className="new-leon-input"
      type_="text"
      value="abcd"
      onChange={_ => ()}
      ref={ReactDOMRe.Ref.domRef(inputRef)}
    />
    <button onClick=handleSelect> "select"->React.string </button>
  </>;
};

Compiler return a bug:

  We've found a bug for you!
  src/components/TestComponent.re 11:41-45
  
   9 ┆ switch (element) {
  10 ┆ | Some(input) =>
  11 ┆   Webapi.Dom.HtmlInputElement.focus(input);
  12 ┆   Webapi.Dom.HtmlInputElement.select(input);
  13 ┆ | None => ()
  
  This has type:
    Dom.htmlElement (defined as
      Dom.eventTarget_like(Dom._node(Dom._element(Dom._htmlElement(Dom._baseClass)))))
  But somewhere wanted:
    Webapi.Dom.HtmlInputElement.t_htmlElement (defined as
      Dom.eventTarget_like(Dom._node(Dom._element(Dom._htmlElement(Dom._htmlInputElement)))))
  
  The incompatible parts:
    Dom._baseClass
    vs
    Dom._htmlInputElement

What is wrong in this code ? This code was working with bs-webapi 0.15.9, with newest: 0.19.1 i have an error above. Maybe there is a bug in library ?
I use bs-platform: 7.3.2

@TheSpyder
Copy link
Contributor

It looks like the type of ofElement has changed to Webapi__Dom__Element.t => option(Dom.htmlElement) instead of option(Dom.htmlInputElement).

And it's another bug from #182 :
https://github.com/reasonml-community/bs-webapi-incubator/pull/182/files?file-filters%5B%5D=.re#diff-f6590c311eac02db4a8591dfe7b1a4c232207269ed2d71105f8407ad4c5ba34dL13-R4

The type annotation on let ofElement: Dom.element => option(t_htmlElement) has been lost (I'm not even sure if it would be valid with the new implementation) so the function becomes effectively useless in scenarios where it's inherited by other modules.

cc @yawaramin

@a-gierczak
Copy link

a-gierczak commented Oct 30, 2020

Hello, any progress of this one? We've run into the same issue trying to access input's value in tests.

@TheSpyder
Copy link
Contributor

Downgrade your version? It has been nearly a month and the maintainer hasn't responded 🤷‍♂️

@Qziem
Copy link
Author

Qziem commented Nov 2, 2020

With 0.18, 0.17, 0.16 i have the same problem. With 0.15.9 works - but no with bs-platform 8.3.1. With bs-platform 8 and bs-webapi 0.15.9 i have an error:

We've found a bug for you!
  /home/leon/public_html/client/react/node_modules/bs-webapi/src/Webapi/Webapi__Dom/Webapi__Dom__DomStringMap.re:11:5-7
  
   9 │ let set = (key, value, map) => set(map, key, value);
  10 │ let unsafeDeleteKey: (key, t) => unit =  
  11 │   [%raw (key, map) => "delete map[key];"];
  12 │   
  
  bs.raw can only be applied to a string

I made workaround to have working with bs-platform 8 and newest bs-webapi, i just created my own functions using %raw (maybe it will be useful for someone):

let focus: Dom.element => unit = [%raw {| domElement => domElement.focus() |}];
let select: Dom.element => unit = [%raw {| domElement => domElement.select() |}];

[@react.component]
let make = () => {
  let inputRef = React.useRef(Js.Nullable.null);

  let handleSelect = _event => {
    let element = inputRef.current->Js.toOption;

    switch (element) {
    | Some(input) =>
      focus(input);
      select(input);
    | None => ()
    };
  };

  <>
    <input
      className="new-leon-input"
      type_="text"
      value="abcd"
      onChange={_ => ()}
      ref={ReactDOMRe.Ref.domRef(inputRef)}
    />
    <button onClick=handleSelect> "select"->React.string </button>
  </>;
};

But of course it would be much better to fix this library.

@TheSpyder
Copy link
Contributor

Oh right, because the library had to be updated to work with some ReScript incompatibilities and this bug was introduced around the same time.

You could use external instead of raw, if you prefer, similar to how webapi does it

[@send] external focus: Dom.element => unit = "focus";
[@send] external select: Dom.element => unit = "select";

and then focus(input) will compile to input.focus().

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants