Re: Form submission participation (was Re: Goals for Shadow DOM review)

On Thu, Feb 20, 2014 at 2:09 PM, Edward O'Connor <eoconnor@apple.com> wrote:
> +public-webapps, -www-tag in replies to avoid cross-posting
>
> Hi,
>
> Domenic wrote, to www-tag:
>
>> [C]an shadow DOM be used to explain existing elements, like <video> or
>> <input type="range">, in terms of a lower-level primitive?
>>
>> As of now, it seems like it cannot, for two reasons:
>>
>> 1. Native elements have extra capabilities which are not granted by
>> shadow DOM, or by custom elements. For example, they can participate
>> in form submission.
>
> Authors need to be able to participate in form submission, but this is
> independent of Custom Elements.
>
> Web applications often maintain state in JS objects that have no direct
> DOM representation. Such applications may want such state to be
> submittable.
>
> Existing form elements map one field name to many values. People often
> build custom controls precisely because those controls hold more
> complex values that would be better represented as many names to many
> values. Subclassing existing form elements don't get you this.
>
> And inheriting from HTMLInputElement is insane (not because inheriting
> is insane, but because HTMLInputElement is insane), so that's not really
> how we want author-defined objects to become submittable.
>
> Given the above I don't think we should try to solve the "how authors
> can participate in form submission" problem by enabling the subclassing
> of existing form elements. Instead, we should define a protocol
> implementable by any JS object, which allows that JS object to expose
> names and values to the form validation and submission processes.
>
> Something like this:
>
>   function Point(x, y) {
>     this.x = x;
>     this.y = y;
>   }
>   Point.prototype.formData = function() {
>     return {
>       "x": this.x,
>       "y": this.y
>     };
>   }
>
>   var theForm = document.querySelector("#my-form");
>
>   var p = new Point(4,2);
>
>   theForm.addParticipant(p);
>   theForm.submit();
>
> This is obviously a super hand-wavy strawman and would need to be
> fleshed out. Thoughts?

Something like this seems awesome! I like that the .addParticipant
function can enable random JS objects to participate in submission. A
couple of comments though:


I'm not sure if we should return a dictionary or an array. Keep in
mind that a form control can have multiple values. This is something
used by both <input multiple> and <select multiple>. Also keep in mind
that order matters as many servers are sensitive to order.

So we could either do `return { x: [5, 6, 7] }` where enumeration
order determines submission order, or we could do `return [["x", 5],
["x", 6], ["x", 7]]`.

Or, given that normally a single form control only has a single name
and 0 to many values, we could do `return { name: "x", value: [5, 6,
7] }`.


The other thing is that it would be great if elements that wanted to
participate in submission didn't have to manually call addParticipant.
This could be done by having the <form> element attempt check for a
.formData property on any descendant that was added, and add any
elements that has such a property as a participant automatically.

We could even make the built-in form controls like <input> and
<select> have a .formData() function which returns data in whatever
format we decide is the right one.

This way custom elements could very easily and automatically
participate in submission by simply declaring a .formData property.

The only tricky part is that form.controls is a live array. I don't
see a way of making form.controls contain custom elements without
synchronously running getters whenever an element is added as a
descendant of a <form>, which is not something we want to do. But live
arrays are evil anyway so we can probably just ignore integration with
that and instead add a form.getParticipants() function which returns a
non-live array of all participants.

/ Jonas

Received on Thursday, 20 February 2014 22:40:28 UTC