element-internals-polyfill icon indicating copy to clipboard operation
element-internals-polyfill copied to clipboard

setFormValue() is incompleted

Open TechQuery opened this issue 4 years ago • 16 comments

What I expect

- setFormValue(value: string)
+ setFormValue(value: string | File | FormData, state: string | File | FormData)

Related links

  • Specification
  • https://github.com/calebdwilliams/element-internals-polyfill/issues/2#issuecomment-734367044

TechQuery avatar Dec 22 '20 18:12 TechQuery

Hey, I'd be happy to take a look at a PR addressing this issue, but I'm not sure of a really good way to do this just yet. I'll do some research. I'll ping @BurnedToast as well. My issue with the comment is that I don't know the best way to determine if you want that element to be a file … maybe I can take a look at the type of data being passed to the first argument of setFormValue and modify the mapped input from there?

Let's chat about this one.

calebdwilliams avatar Dec 28 '20 22:12 calebdwilliams

My scenario is similar with https://web.dev/more-capable-form-controls/#setting-a-value .

My Preview File Input component needs to set a File value.

TechQuery avatar Dec 29 '20 07:12 TechQuery

I also thought about opening a new issue on this one. Thanks @TechQuery for doing so. The determination is pretty simple i guess. You just need to do an value instanceof File check.

I am currently on vacation, but i could invest some more time into this one next year :)

BurnedToast avatar Dec 29 '20 08:12 BurnedToast

@BurnedToast @calebdwilliams Happy new year, stay strong, and away from COVID-19~

TechQuery avatar Dec 29 '20 13:12 TechQuery

Looking at this again, I'm not sure it makes sense to add because there doesn't appear to be a reliable way to support this feature in Safari. One of the goals here should be to create a consistent experience as best we can. Having this work in Firefox and not in Safari (or IE11/older versions of Edge) could lead to some apps not working. I'm tempted to mark this as won't fix due to that. I'll keep seeing if there are work arounds for Safari though.

Edit Here is a Pen with the above technique if you want to play with it in Safari/Firefox/Chrome. If we can figure out how to get consistent behavior across those three (IE11/legacy Edge is a nice to have), I will definitely get this added ASAP.

calebdwilliams avatar Dec 29 '20 17:12 calebdwilliams

After some research I could not find any solution for Safari, that could be integrated into this polyfill.

But I found a possible workaround for my use case, that should also work for you @TechQuery. As shown above, there is currently no way to create a new FileList in Safari etc. But you dont need a new mutable list if you just want a 100% copy of an input-file-element from within your shadow dom.

So you could just handle a hidden input-file-element by your own and copy the files property. Here is a code pen showing how to transfer the selected files from one input to another: https://codepen.io/burnedtoast/pen/YzGaBWY

The creation of the "ghost input" outside the shadow root is not included. Hope this helps

BurnedToast avatar Jan 04 '21 07:01 BurnedToast

For my FileUpload-Component, that internally uses an input type="file" element, I ended up using attachInternals() to get support for all the other polyfilled stuff (validation etc).

I just replaced the code for "elementInternals.setFormValue" with the following:

if (ElementInternals.isPolyfilled) {
  // only do the workaround when using the polyfill
  if (!this.outOfShadowRootInput) {
    // convert the polyfill input element to type file and hide it by display=none
    this.outOfShadowRootInput = this.elementRef.nativeElement.nextElementSibling;
    this.outOfShadowRootInput.setAttribute('type', 'file');
    this.outOfShadowRootInput.style.display = 'none';
  }
  // transfer the file list from the internal input element to the polyfill element
  this.outOfShadowRootInput.files = this.getInputElement().files;
} else {
  // use the native way
  this.internals.setFormValue(this.getInputElement().files);
}
  • It is a AngularElements code example
  • this.elementRef.nativeElement is the host element of my webcomponent
  • this.outOfShadowRootInput is the hidden polyfill input element
  • this.internals is the ElementInternals-Object returned by attachInternals
  • this.getInputElement() returns the HtmlInputElement for the file selection from within my webcomponent / shadow dom
  • The else case is untested

BurnedToast avatar Jan 04 '21 09:01 BurnedToast

@BurnedToast Thanks your example codes~

My File Input component did use <input type="file" hidden /> before, but now I pefer a polyfill way in my code.

I feel sad for Safari users...

TechQuery avatar Jan 04 '21 10:01 TechQuery

Same. My buddy recently put this together to illustrate that web devs now have a new problem on our hands.

I’m going to keep this issue open and hopefully add a caveat to the README about this. I am interested in any solution that hits all modern browsers (bonus points for IE11 compatibility).

calebdwilliams avatar Jan 04 '21 13:01 calebdwilliams

@calebdwilliams Thanks your buddy, and I'll show https://issafarithenewie.com/ to my clients~

Add one more reason to this site: Every browser on iOS is Safari indeed !

TechQuery avatar Jan 04 '21 19:01 TechQuery

@TechQuery @BurnedToast this seems to work in the latest version of Safari based on the Pen linked above. Can anyone confirm? If so, is anyone interested in opening up a PR for this?

calebdwilliams avatar Jan 27 '22 23:01 calebdwilliams

Following up @TechQuery, @BurnedToast is this still a need?

calebdwilliams avatar Jan 06 '23 02:01 calebdwilliams

I did not had the opportunity to test this, since I do not have any Safari test devices currently. Hope this will change soon. I will give some Feedback, when I get my hands on any.

BurnedToast avatar Jan 06 '23 12:01 BurnedToast

I did not had the opportunity to test this, since I do not have any Safari test devices currently. Hope this will change soon. I will give some Feedback, when I get my hands on any.

Me too, I'm a Windows/Linux user.

TechQuery avatar Jan 06 '23 18:01 TechQuery

setFormValue breaks compilation: https://github.com/calebdwilliams/element-internals-polyfill/blob/main/src/element-internals.ts#L168 is missing the File type in the first argument.

CleanShot 2024-01-10 at 13 08 43@2x

jpzwarte avatar Jan 10 '24 12:01 jpzwarte

@calebdwilliams too busy to create a PR atm, but if you want to use the same typing as Typescript, try this: export type FormValue = Parameters<ElementInternals['setFormValue']>[0];

jpzwarte avatar Jan 10 '24 12:01 jpzwarte