vscode-webview-ui-toolkit icon indicating copy to clipboard operation
vscode-webview-ui-toolkit copied to clipboard

VSCodeButton does not trigger a submit event on the form it belongs to, overriding the default behavior of buttons in forms.

Open MichaelHindley opened this issue 2 years ago • 7 comments

Describe the bug

VSCodeButton does not trigger a submit event on the form it belongs to, overriding the default behavior of buttons in forms.

Working workaround is to explicitly add the type="submit" prop.

To reproduce

Inside a webview panel:

        <form onSubmit={(e) => {
          e.preventDefault()
          console.log(e) // logs
        }}>
          <button>Button</button>
        </form>


        <form onSubmit={(e) => {
          e.preventDefault()
          console.log(e) // does not log
        }}>
         
          <VSCodeButton>Button</VSCodeButton>
        </form>

        <form onSubmit={(e) => {
          e.preventDefault()
          console.log(e) // logs
        }}>
          <VSCodeButton type="submit">Button</VSCodeButton>
        </form>

Desktop (please complete the following information):

  • OS Version: [e.g. macOS 12.4]
  • Toolkit Version: [e.g. v1.0.0]

MichaelHindley avatar Aug 21 '22 19:08 MichaelHindley

Thanks for the report @MichaelHindley!

I already have it on my list to do a deeper dive into VS Code webview form usage so I'll fold this into that work.

hawkticehurst avatar Aug 22 '22 21:08 hawkticehurst

@hawkticehurst Any news about this problem?

AlencarGabriel avatar Jan 20 '23 21:01 AlencarGabriel

Hey @AlencarGabriel! No breakthrough updates yet

I've been testing/debugging this issue (along with the other form-related issues) as I've had pockets of time during the last few months and I'm starting to think this might actually be an upstream issue with FAST (the framework we use to build the toolkit components) but I still want to do some more testing before I feel confident about it

We're also pretty tightly resourced at this time (myself and one other person split our time between this and a handful of other projects) so it still might take a while to finally wrap this all up but steady progress has been made and I'll try to give updates as I find out more :)

hawkticehurst avatar Mar 21 '23 22:03 hawkticehurst

@hawkticehurst I completely understand and I'm glad this matter didn't fall by the wayside. I did some simple tests using FAST natively and the behavior seems to be related to VSCode's button component.

AlencarGabriel avatar Mar 22 '23 12:03 AlencarGabriel

Oh yes, it definitely did not fall by the wayside -- reliably (and accessibly) accepting user input is pretty dang important so it's very much up there on my list of things to finish asap 😅

Also ahh! What a brilliantly simple way of validating whether FAST is the root cause or not. I've been so deep in the weeds that the thought never even crossed my mind -- thank you for mentioning it!

Out of curiosity could you tell me a bit more of how tested this? Namely, was this tested in browser or in a webview? Did you create a button component from scratch or use fast-foundation? Did you wrap the FAST component in a React component? Etc etc. Thanks in advance :)

hawkticehurst avatar Mar 22 '23 18:03 hawkticehurst

@hawkticehurst I made a POC to facilitate your test.

The behavior occurs both in the browser and in vscode's webview.

The idea is that when clicking on a button, or on the ENTER event of the input, the submit event of the form is triggered. In that case I don't need the ACTION event (I think it doesn't make much sense in these webviews either).

In this POC, when pressing ENTER at the input or clicking on the FAST native button, the submit event is triggered. The VSCode toolkit button does not trigger the submit.

Scripts import:

  • /node_modules/@vscode/webview-ui-toolkit/dist/toolkit.js
  • /node_modules/@microsoft/fast-components/dist/fast-components.js

main.js:

const vscode = acquireVsCodeApi();

window.addEventListener("load", main);

function main() {
    const form = document.querySelector("form");
    form.addEventListener("submit", (event) => {
        console.log("submit");
        event.preventDefault();
    });
}

webview body content:

<form>
    <vscode-text-field placeholder="Text of placeholder"></vscode-text-field>
    <fast-button type="submit">Fast Submit</fast-button>
    <vscode-button type="submit">VsCode Sumit</vscode-button>
</form>

Hope it helps ;)

AlencarGabriel avatar Mar 23 '23 18:03 AlencarGabriel

Annoyingly the way I had to solve this (in a React project) is by the following:

export function FeedbackDialog() {
  const formEl = useRef<HTMLFormElement>(null);

  const handleSubmit = () => {
    const form = formEl.current!;
    const isValid = form.reportValidity();

    if (!isValid) {
      return;
    }

    const formData = new FormData(formEl.current!);
    sendToAPI(formData);
  };

  return (
      <form ref={formEl}>
        <VSCodeTextArea
          required
          name="feedback"
          cols={0}
          rows={6}
          placeholder="Enter text..."
        />
        <div>
          <VSCodeButton onClick={handleSubmit}>Send</VSCodeButton>
        </div>
      </form>
  );
}

I hope this helps some folks

andrico-anima avatar Mar 22 '24 15:03 andrico-anima