Monday, February 3, 2014

The Strange Case of Submitting Forms Containing Polymers


OK, I have a ridiculous questions. I mean more ridiculous that usual. What happens when a plain old form is submitted containing a Polymer?

Hopefully this will be a relatively easy question to answer. With 12 days left before the first edition of Patterns in Polymer is due, I need to slam out 5 more chapters (starting with the Angular chapter) and edit like a madman. That means scaling back the research. So fingers-crossed that I really have left the easier questions for last.

I suspect that input fields contained inside the Polymer (either projected or embedded) will be submitted right along with the input fields from the form in the main web page. There is one good way to find out. I start by modifying an example Polymer.dart application:
      <form action="test" method="post">
        <input type=text name="plain_old_param">
        <hello-you>
          <input type=text name="distributed_param">
        </hello-you>
        <input type=submit value=Play>
      </form>
The plain_old_param input field will definitely be submitted when the form is submitted—it's a plain-old form parameter. The distributed_param, which will be projected into the shadow DOM of the <hello-you> Polymer ought be submitted, as should the value of <input value="{{your_name}}"> directly inside of the Polymer. I think…

As it turns out, when I submit this form:



The only form variables that are being submitted are:
plain_old_param:plain
distributed_param:projected
That surprises me. I believe that this can be explained as the <input> inside the Polymer being part of the shadow DOM and, therefore not as a child of the <form> element in the page. Along those same lines, the projected <input> is just that—projected. It remains a child of the <form> in the main page even though it is rendered inside (projected into) the Polymer's <content> tags. Still, I thought the shadow DOM being attached to the <hello-you> Polymer, which is a child of the <form> would allow the Polymer's <input> field to be considered as part of the <form> as well. I was wrong.

That explanation is seemingly supported by the live DOM tree which includes the plain and projected <input> fields as active children of the <form> whereas the Polymer's input fields are children of a separate document fragment (the Polymer's shadow DOM):



As long as I understand that this is the case, I can live with it. Except…

It does not work that way in the JavaScript equivalent. While the Dart version of the Polymer places the entire contents of the <hello-you> element in its own document fragment, then JavaScript version places most of it directly on the page:



And, as such, when I submit the form, the embedded form parameter is submitted:
plain_old_param:plain
embedded_polymer_param:embedded
distributed_param:projected
Ugh.

I think my takeaway from all of this is that you'd be crazy to rely on <input> fields inside Polymers as plain-old <form> inputs. For the most part, that is not a hardship as many of these things will be embedded into an Angular application (or equivalent) in which case data binding can be used. But dang it, sometime folks will want to submit the data contained in these directly to a servers. Seems like I may need a chapter on this as well.


Day #1,016

No comments:

Post a Comment