Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #39235 > unrolled thread

Painted into a corner

Started byAndrew Poulos <ap_prog@hotmail.com>
First post2020-12-07 13:54 +1100
Last post2020-12-07 02:07 -0800
Articles 14 — 4 participants

Back to article view | Back to comp.lang.javascript


Contents

  Painted into a corner Andrew Poulos <ap_prog@hotmail.com> - 2020-12-07 13:54 +1100
    Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-07 04:25 +0100
      Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-07 04:44 +0100
        Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-07 19:50 +0100
          Re: Painted into a corner Andrew Poulos <ap_prog@hotmail.com> - 2020-12-08 12:26 +1100
            Re: Painted into a corner "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2020-12-08 07:07 -0800
              Re: Painted into a corner Andrew Poulos <ap_prog@hotmail.com> - 2020-12-09 08:07 +1100
                Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-10 17:59 +0100
            Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-09 17:09 +0100
              Re: Painted into a corner Andrew Poulos <ap_prog@hotmail.com> - 2020-12-12 13:01 +1100
                Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-12 10:46 +0100
    Re: Painted into a corner "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2020-12-06 19:55 -0800
      Re: Painted into a corner Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2020-12-07 19:51 +0100
    Re: Painted into a corner Julio Di Egidio <julio@diegidio.name> - 2020-12-07 02:07 -0800

#39235 — Painted into a corner

FromAndrew Poulos <ap_prog@hotmail.com>
Date2020-12-07 13:54 +1100
SubjectPainted into a corner
Message-ID<CrOdnaj9_ITsBFDCnZ2dnUU7-VfNnZ2d@westnet.com.au>
I've coded a page with a form containing a number of "components". One 
component (called the Image component) has a tabset that and 50+ inputs 
(radio buttons, text fields, colour inputs, number inputs...) Each input 
has an ID.

The Image component's job is to configure an image (size, position, 
filters...)

To capture the values I simply serialise the form into an array of 
objects (the array ends up with several hundred objects) eg.

...
{type: "number", id: "imgWidth", value: "0", disabled: false, checked: 
false}
{type: "checkbox", id: "imgGrayscaleCbx", value: "on", disabled: false, 
checked: false}
{type: "range", id: "imgGrayscaleRange", value: "0", disabled: true, 
checked: false}
...

I believed that only ONE image will ever be needed. Now I'm tasked with 
dealing with an unlimited number of images - up to, say, 24 images.

What I'm stuck on is how to serialise/get the values for multiple 
images. If I clone the component for each image then there'll be 
multiple elements with the same ID (and 20 images will mean 1000+ inputs).

If I increment a counter and add it to the ID (so for the second Image 
"imgWidth1" becomes imgWidth2" and the third "imgWidth3" what happens 
then if the user decides to delete the second image? I'll have 
"imgWidth1" and "imgWidth3" but no "imgWidth2".

Is there some generalised way I can approach a solution for this?

Andrew Poulos

[toc] | [next] | [standalone]


#39236

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-07 04:25 +0100
Message-ID<11650524.O9o76ZdvQC@PointedEars.de>
In reply to#39235
Andrew Poulos wrote:

> I've coded a page with a form containing a number of "components". One
> component (called the Image component) has a tabset that and 50+ inputs
> (radio buttons, text fields, colour inputs, number inputs...) Each input
> has an ID.
> 
> The Image component's job is to configure an image (size, position,
> filters...)
> 
> To capture the values I simply serialise the form into an array of
> objects (the array ends up with several hundred objects) eg.
> 
> ...
> {type: "number", id: "imgWidth", value: "0", disabled: false, checked:
> false}
> {type: "checkbox", id: "imgGrayscaleCbx", value: "on", disabled: false,
> checked: false}
> {type: "range", id: "imgGrayscaleRange", value: "0", disabled: true,
> checked: false}
> ...
> 
> I believed that only ONE image will ever be needed. Now I'm tasked with
> dealing with an unlimited number of images - up to, say, 24 images.
> 
> What I'm stuck on is how to serialise/get the values for multiple
> images. If I clone the component for each image then there'll be
> multiple elements with the same ID (and 20 images will mean 1000+ inputs).
> 
> If I increment a counter and add it to the ID (so for the second Image
> "imgWidth1" becomes imgWidth2" and the third "imgWidth3" what happens
> then if the user decides to delete the second image? I'll have
> "imgWidth1" and "imgWidth3" but no "imgWidth2".
> 
> Is there some generalised way I can approach a solution for this?

The old and proofed solution: Give controls of the same type the same “name” 
[attribute value] instead of an ID, and iterate over the NodeList that is 
automatically created then:

  let elements = form.elements;
  Array.from(elements['imgWidth']).forEach((control, index) => {
    /* serialize control */

    /* serialize elements['imgGrayscaleCbx'][index] */

    /* serialize elements['imgGrayscaleRange'][index] */
  });

The NodeList is live, so if the user decides to delete the base control 
(here: referred by “control”), this is not a problem.

I am pretty sure that bullet-proof form serialization code has already been 
written several times.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39237

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-07 04:44 +0100
Message-ID<5415173.DvuYhMxLoT@PointedEars.de>
In reply to#39236
Thomas 'PointedEars' Lahn wrote:

> I am pretty sure that bullet-proof form serialization code has already
> been written several times.

Consider this quickhack:

  var form = document.forms[0];
  var elements = form.elements;
  var data = Object.create(null);

  Array.from(elements).forEach((control) => {
    if (!control.name) return;

    var record = {
      type: control.type,
      value: control.value,
      disabled: control.disabled
    };
    
    if (!(control.name in data))
    {
      data[control.name] = record;
    }
    else
    {
      data[control.name] = [].concat(data[control.name], record);
    }
  });

  console.log(data);

I discovered on this occasion

  [].concat(any, record)

to be a nice way to put values in an Array regardless whether there already 
was one :)

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39247

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-07 19:50 +0100
Message-ID<5663081.lOV4Wx5bFT@PointedEars.de>
In reply to#39237
Thomas 'PointedEars' Lahn wrote:

>     
>     if (!(control.name in data))
>     {
>       data[control.name] = record;
>     }
>     else
>     {
>       data[control.name] = [].concat(data[control.name], record);
>     }

Minor optimization:

  data[control.name] =
    (control.name in data)
      ? [].concat(data[control.name], record)
      : record;

If you always want the data-per-key in an array then you can just write

  data[control.name] = [].concat(data[control.name], record);

Another possibility:
  
  var name = control.name;
  var value = data[name];
  (Array.isArray(value)
    ? value
    : data[name] = (name in data ? [value] : [])
  ).push(record);

The latter approach has the advantage over the previous two that no 
superfluous Array instances will be created.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39257

FromAndrew Poulos <ap_prog@hotmail.com>
Date2020-12-08 12:26 +1100
Message-ID<XKqdnfj-ouveS1PCnZ2dnUU7-U_NnZ2d@westnet.com.au>
In reply to#39247
On 8/12/2020 5:50 am, Thomas 'PointedEars' Lahn wrote:
> Thomas 'PointedEars' Lahn wrote:
> 
>>      
>>      if (!(control.name in data))
>>      {
>>        data[control.name] = record;
>>      }
>>      else
>>      {
>>        data[control.name] = [].concat(data[control.name], record);
>>      }
> 
> Minor optimization:
> 
>    data[control.name] =
>      (control.name in data)
>        ? [].concat(data[control.name], record)
>        : record;
> 
> If you always want the data-per-key in an array then you can just write
> 
>    data[control.name] = [].concat(data[control.name], record);
> 
> Another possibility:
>    
>    var name = control.name;
>    var value = data[name];
>    (Array.isArray(value)
>      ? value
>      : data[name] = (name in data ? [value] : [])
>    ).push(record);
> 
> The latter approach has the advantage over the previous two that no
> superfluous Array instances will be created.

Thanks for that. Still I'm having trouble.

Rather than making multiple copies of the same "Image" component I was 
thinking to just use one and set/reset it when the user adds another image.

But currently all the UI components are "within" a single form so if 
the user adds an "Image" there's no way it's values can be separated 
from any other "Image's" values.

Should I just clone the "Image" so that form elements exist for every 
"Image"? (Though for 10 Images that means 1,000+ inputs added to the HTML.)

Andrew Poulos

[toc] | [prev] | [next] | [standalone]


#39258

From"Michael Haufe (TNO)" <tno@thenewobjective.com>
Date2020-12-08 07:07 -0800
Message-ID<e1864e09-95a9-44c1-8dc7-c78eae7c37fen@googlegroups.com>
In reply to#39257
On Monday, December 7, 2020 at 7:26:38 PM UTC-6, Andrew Poulos wrote:
> On 8/12/2020 5:50 am, Thomas 'PointedEars' Lahn wrote: 
> > Thomas 'PointedEars' Lahn wrote: 
> > 
> >> 
> >> if (!(control.name in data)) 
> >> { 
> >> data[control.name] = record; 
> >> } 
> >> else 
> >> { 
> >> data[control.name] = [].concat(data[control.name], record); 
> >> } 
> > 
> > Minor optimization: 
> > 
> > data[control.name] = 
> > (control.name in data) 
> > ? [].concat(data[control.name], record) 
> > : record; 
> > 
> > If you always want the data-per-key in an array then you can just write 
> > 
> > data[control.name] = [].concat(data[control.name], record); 
> > 
> > Another possibility: 
> > 
> > var name = control.name; 
> > var value = data[name]; 
> > (Array.isArray(value) 
> > ? value 
> > : data[name] = (name in data ? [value] : []) 
> > ).push(record); 
> > 
> > The latter approach has the advantage over the previous two that no 
> > superfluous Array instances will be created.
> Thanks for that. Still I'm having trouble. 
> 
> Rather than making multiple copies of the same "Image" component I was 
> thinking to just use one and set/reset it when the user adds another image. 
> 
> But currently all the UI components are "within" a single form so if 
> the user adds an "Image" there's no way it's values can be separated 
> from any other "Image's" values. 
> 
> Should I just clone the "Image" so that form elements exist for every 
> "Image"? (Though for 10 Images that means 1,000+ inputs added to the HTML.) 


Did you try using FormData?

[toc] | [prev] | [next] | [standalone]


#39259

FromAndrew Poulos <ap_prog@hotmail.com>
Date2020-12-09 08:07 +1100
Message-ID<YbKdnSTZdYaMdlLCnZ2dnUU7-Q3NnZ2d@westnet.com.au>
In reply to#39258
On 9/12/2020 2:07 am, Michael Haufe (TNO) wrote:
> On Monday, December 7, 2020 at 7:26:38 PM UTC-6, Andrew Poulos wrote:
>> On 8/12/2020 5:50 am, Thomas 'PointedEars' Lahn wrote:
>>> Thomas 'PointedEars' Lahn wrote:
>>>
>>>>
>>>> if (!(control.name in data))
>>>> {
>>>> data[control.name] = record;
>>>> }
>>>> else
>>>> {
>>>> data[control.name] = [].concat(data[control.name], record);
>>>> }
>>>
>>> Minor optimization:
>>>
>>> data[control.name] =
>>> (control.name in data)
>>> ? [].concat(data[control.name], record)
>>> : record;
>>>
>>> If you always want the data-per-key in an array then you can just write
>>>
>>> data[control.name] = [].concat(data[control.name], record);
>>>
>>> Another possibility:
>>>
>>> var name = control.name;
>>> var value = data[name];
>>> (Array.isArray(value)
>>> ? value
>>> : data[name] = (name in data ? [value] : [])
>>> ).push(record);
>>>
>>> The latter approach has the advantage over the previous two that no
>>> superfluous Array instances will be created.
>> Thanks for that. Still I'm having trouble.
>>
>> Rather than making multiple copies of the same "Image" component I was
>> thinking to just use one and set/reset it when the user adds another image.
>>
>> But currently all the UI components are "within" a single form so if
>> the user adds an "Image" there's no way it's values can be separated
>> from any other "Image's" values.
>>
>> Should I just clone the "Image" so that form elements exist for every
>> "Image"? (Though for 10 Images that means 1,000+ inputs added to the HTML.)
> 
> 
> Did you try using FormData?

What I've done (which now looks to be a mistake) is to have all the UI 
components in one form. I'm unsure how to use FormData to make multiple 
copies of one part of the form.

Andrew Poulos

[toc] | [prev] | [next] | [standalone]


#39261

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-10 17:59 +0100
Message-ID<4583459.GXAFRqVoOG@PointedEars.de>
In reply to#39259
Andrew Poulos wrote:

> On 9/12/2020 2:07 am, Michael Haufe (TNO) wrote:
>> Did you try using FormData?
> 
> What I've done (which now looks to be a mistake)

That is not a mistake; it is the standard way, and recommended in order to 
have a form that even works without scripting.

> is to have all the UI components in one form. I'm unsure how to use
> FormData to make multiple copies of one part of the form.

I think Michael only referred to your serialization issues.

Please trim your quotes.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39260

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-09 17:09 +0100
Message-ID<2178622.ElGaqSPkdT@PointedEars.de>
In reply to#39257
Andrew Poulos wrote:

> Rather than making multiple copies of the same "Image" component I was
> thinking to just use one and set/reset it when the user adds another
> image.
> 
> But currently all the UI components are "within" a single form so if
> the user adds an "Image" there's no way it's values can be separated
> from any other "Image's" values.

Why not?  AISB, form controls with the same name are automatically indexed 
in the DOM.  Suppose your “Image” component looks like this:

  <form id="f-images">
    <div class="c-image">
      <input type="number" name="imgWidth" value="0">
      <input type="checkbox" name="imgGrayscaleCbx" checked>
      <input type="range" name="imgGrayscaleRange" value="0" disabled>
    </div>

Then if you have another component

    <div class="c-image">
      <input type="number" name="imgWidth" value="42">
      <input type="checkbox" name="imgGrayscaleCbx">
      <input type="range" name="imgGrayscaleRange" value="1" disabled>
    </div>
  </form>

then the controls of the first component can be referred to by

  form.elements['imgWidth'][0]
  form.elements['imgGrayscaleCbx'][0]
  form.elements['imgGrayscaleRange'][0]

and the controls of the second component by

  form.elements['imgWidth'][1]
  form.elements['imgGrayscaleCbx'][1]
  form.elements['imgGrayscaleRange'][1]

whereas previously

  let form = document.forms['f-images'];

    [Historically one would have used names like “imgWidth[]” to indicate
     the NodeList; IIRC, it still makes a difference in PHP.]

It does not matter if the second component was already there (in the markup) 
or if the user performed an action so that it was inserted into the document 
tree.  And as the NodeList is live, it does not matter if the user deletes 
the first component.  So you can iterate over one of those NodeLists, e.g. 
form.elements['imgWidth'], to access (and serialize) the corresponding 
controls.
 
> Should I just clone the "Image" so that form elements exist for every
> "Image"? (Though for 10 Images that means 1,000+ inputs added to the
> HTML.)

If this is not supposed to work without scripting anyway, and requires no 
user interaction then you should store the data in an array right away, and 
forget about form serialization.

Otherwise it is a good idea to add a new instance of the component.  If you 
do that by cloning markup, then you should clone properly initialized 
template markup and not the markup of another instance of the component.

If none of this makes sense to you, then you have to elaborate on your
use-case.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39265

FromAndrew Poulos <ap_prog@hotmail.com>
Date2020-12-12 13:01 +1100
Message-ID<z4ednSoWJ_4QuUnCnZ2dnUU7-fPNnZ2d@westnet.com.au>
In reply to#39260
On 10/12/2020 3:09 am, Thomas 'PointedEars' Lahn wrote:
> Andrew Poulos wrote:
> 
>> Rather than making multiple copies of the same "Image" component I was
>> thinking to just use one and set/reset it when the user adds another
>> image.
>>
>> But currently all the UI components are "within" a single form so if
>> the user adds an "Image" there's no way it's values can be separated
>> from any other "Image's" values.
> 
> Why not?  AISB, form controls with the same name are automatically indexed
> in the DOM.  Suppose your “Image” component looks like this:
> 
>    <form id="f-images">
>      <div class="c-image">
>        <input type="number" name="imgWidth" value="0">
>        <input type="checkbox" name="imgGrayscaleCbx" checked>
>        <input type="range" name="imgGrayscaleRange" value="0" disabled>
>      </div>
> 
> Then if you have another component
> 
>      <div class="c-image">
>        <input type="number" name="imgWidth" value="42">
>        <input type="checkbox" name="imgGrayscaleCbx">
>        <input type="range" name="imgGrayscaleRange" value="1" disabled>
>      </div>
>    </form>
> 
> then the controls of the first component can be referred to by
> 
>    form.elements['imgWidth'][0]
>    form.elements['imgGrayscaleCbx'][0]
>    form.elements['imgGrayscaleRange'][0]
> 
> and the controls of the second component by
> 
>    form.elements['imgWidth'][1]
>    form.elements['imgGrayscaleCbx'][1]
>    form.elements['imgGrayscaleRange'][1]
> 
> whereas previously
> 
>    let form = document.forms['f-images'];

I found that if I leave the first instance using IDs and the subsequent 
instances using 'names' then
   let form = document.forms['f-images'];
finds both. (This means I don't need to change my working code that uses 
IDs.)

>      [Historically one would have used names like “imgWidth[]” to indicate
>       the NodeList; IIRC, it still makes a difference in PHP.]
> 
> It does not matter if the second component was already there (in the markup)
> or if the user performed an action so that it was inserted into the document
> tree.  And as the NodeList is live, it does not matter if the user deletes
> the first component.  So you can iterate over one of those NodeLists, e.g.
> form.elements['imgWidth'], to access (and serialize) the corresponding
> controls.

I didn't know that the NodeList was live. I've been calling it  every 
time I needed to work with it.

>> Should I just clone the "Image" so that form elements exist for every
>> "Image"? (Though for 10 Images that means 1,000+ inputs added to the
>> HTML.)
> 
> If this is not supposed to work without scripting anyway, and requires no
> user interaction then you should store the data in an array right away, and
> forget about form serialization.

I'm don't understand how I supposed to store a form's data into an array 
without serialising the form. Do you mean something like
   const form_array = Array.from(form_data);

> Otherwise it is a good idea to add a new instance of the component.  If you
> do that by cloning markup, then you should clone properly initialized
> template markup and not the markup of another instance of the component.

Yes, I got caught when I tried to clone elements with IDs.

> If none of this makes sense to you, then you have to elaborate on your
> use-case.

Thanks for the help.

Andrew Poulos

[toc] | [prev] | [next] | [standalone]


#39266

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-12 10:46 +0100
Message-ID<1768183.tdWV9SEqCh@PointedEars.de>
In reply to#39265
Andrew Poulos wrote:

> On 10/12/2020 3:09 am, Thomas 'PointedEars' Lahn wrote:
>> […]
>> and the controls of the second component by
>> 
>>    form.elements['imgWidth'][1]
>>    form.elements['imgGrayscaleCbx'][1]
>>    form.elements['imgGrayscaleRange'][1]
>> 
>> whereas previously
>> 
>>    let form = document.forms['f-images'];
> 
> I found that if I leave the first instance using IDs and the subsequent
> instances using 'names' then
>    let form = document.forms['f-images'];
> finds both. (This means I don't need to change my working code that uses
> IDs.)

This was meant to refer to *the form*, and I think there should be only one 
form for the same purpose for the reason that I mentioned.

However if it works for the form *controls* of an “Image” component for you, 
so much the better.

But what if the user deletes the first instance?

> I didn't know that the NodeList was live.

Well, I told you before :-p

<news:11650524.O9o76ZdvQC@PointedEars.de>

>>> Should I just clone the "Image" so that form elements exist for every
>>> "Image"? (Though for 10 Images that means 1,000+ inputs added to the
>>> HTML.)
>> 
>> If this is not supposed to work without scripting anyway, and requires no
>> user interaction then you should store the data in an array right away,
>> and forget about form serialization.
> 
> I'm don't understand how I supposed to store a form's data into an array
> without serialising the form. Do you mean something like
>    const form_array = Array.from(form_data);

I meant that you *could* forget that it is a form if it is *not* directly 
interactive.  Then you would keep elsewhere the data to be submitted.
 
>> If none of this makes sense to you, then you have to elaborate on your
>> use-case.
> 
> Thanks for the help.

You’re welcome :)

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39238

From"Michael Haufe (TNO)" <tno@thenewobjective.com>
Date2020-12-06 19:55 -0800
Message-ID<3f4503a7-d1d6-49cc-8d19-68738e3e9e58n@googlegroups.com>
In reply to#39235
On Sunday, December 6, 2020 at 8:54:55 PM UTC-6, Andrew Poulos wrote:
> I've coded a page with a form containing a number of "components". One 
> component (called the Image component) has a tabset that and 50+ inputs 
> (radio buttons, text fields, colour inputs, number inputs...) Each input 
> has an ID. 
> 
> The Image component's job is to configure an image (size, position, 
> filters...) 
> 
> To capture the values I simply serialise the form into an array of 
> objects (the array ends up with several hundred objects) eg. 
> 
> ... 
> {type: "number", id: "imgWidth", value: "0", disabled: false, checked: 
> false} 
> {type: "checkbox", id: "imgGrayscaleCbx", value: "on", disabled: false, 
> checked: false} 
> {type: "range", id: "imgGrayscaleRange", value: "0", disabled: true, 
> checked: false} 
> ... 
> 
> I believed that only ONE image will ever be needed. Now I'm tasked with 
> dealing with an unlimited number of images - up to, say, 24 images. 
> 
> What I'm stuck on is how to serialise/get the values for multiple 
> images. If I clone the component for each image then there'll be 
> multiple elements with the same ID (and 20 images will mean 1000+ inputs). 
> 
> If I increment a counter and add it to the ID (so for the second Image 
> "imgWidth1" becomes imgWidth2" and the third "imgWidth3" what happens 
> then if the user decides to delete the second image? I'll have 
> "imgWidth1" and "imgWidth3" but no "imgWidth2". 
> 
> Is there some generalised way I can approach a solution for this? 

Try using the FormData object:

<https://developer.mozilla.org/en-US/docs/Web/API/FormData>

```
let frm = document.getElementById("frm"),
  out = document.getElementById("out");

frm.addEventListener("submit", (e) => {
  e.preventDefault();
  let formData = new FormData(frm);
  out.innerHTML = "";
  for (let [key, value] of formData.entries()) {
    let li = document.createElement("li");
    li.textContent = `key: ${key}; value: ${value}`;
    out.appendChild(li);
  }
});
```

For a form with duplicate fields (like 'c') you'll get the following output:

```
key: c; value: red
key: c; value: green
key: c; value: blue
```

[toc] | [prev] | [next] | [standalone]


#39248

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2020-12-07 19:51 +0100
Message-ID<4608983.31r3eYUQgx@PointedEars.de>
In reply to#39238
Michael Haufe (TNO) wrote:

> On Sunday, December 6, 2020 at 8:54:55 PM UTC-6, Andrew Poulos wrote:
>> Is there some generalised way I can approach a solution for this?
> 
> Try using the FormData object:
> 
> <https://developer.mozilla.org/en-US/docs/Web/API/FormData>

I suspected that by now there would be a standardized method.  Thank you.
 
-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#39240

FromJulio Di Egidio <julio@diegidio.name>
Date2020-12-07 02:07 -0800
Message-ID<934f1379-fd11-4298-9d22-98dfc681a3c0n@googlegroups.com>
In reply to#39235
On Monday, 7 December 2020 at 03:54:55 UTC+1, Andrew Poulos wrote:
> I've coded a page with a form containing a number of "components". One 
> component (called the Image component)
<snip>

Call it "ImageSettings section" (or similar): naming is half of the job.
The other half of the trouble here (still for what I can surmise from
your description) is that you are serializing form elements instead of
serializing settings values, so conflating abstractions to begin with.

> I believed that only ONE image will ever be needed. Now I'm tasked with 
> dealing with an unlimited number of images - up to, say, 24 images. 
> 
> What I'm stuck on is how to serialise/get the values for multiple 
> images. If I clone the component for each image then there'll be 
> multiple elements with the same ID (and 20 images will mean 1000+ inputs). 

Equal IDs in the same one page is simply invalid HTML: IDs must be
unique, which is the whole point of IDs.

> If I increment a counter and add it to the ID (so for the second Image 
> "imgWidth1" becomes imgWidth2" and the third "imgWidth3" what happens 
> then if the user decides to delete the second image? I'll have 
> "imgWidth1" and "imgWidth3" but no "imgWidth2".

E.g. items in an array do not come with an ID, yet you can work with those.
IOW, it is not even clear why you should have any trouble here.  Indeed, say
you scan the page and collect all elements that you find in the order you
find them: isn't that just it?  What does it even matter how the user builds
up the form (if that's what you mean) re its serialization/deserialization?

OTOH, say you do not want to blindly serialize all elements in the page,
you could then intercept user additions/deletions (as I suppose you do
provide the mechanisms to do so, users don't just mangle the HTML
source directly) and maintain a list of references to the existing elements
there?

I mean, there may be so many variants depending on specifics and
needs, still no real problem in sight...

> Is there some generalised way I can approach a solution for this?

Very generally: there is no solution until there is a well-posed problem.

Julio

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web