eugene1832 eugene1832 - 3 months ago 22
Jade Question

Pug (RIP Jade) form checkboxes - only one value returned regardless how many selected

I have a form written in Pug. I am getting all the correct parameters out of the form's POST, except my checkbox array is a string containing one value - the latest day selected. Each checkbox has a name equaling an array, so the form should be returning all selected checkboxes. However, that is not happening.

Here is the relevant code in the form for the checkbox selection:

form#create-shift-form(action='/shifts/new', method='post')
div.form-group
p Select which days this shift should apply:
div.checkbox-inline
input.checkbox-input#create-shift-mon(type='checkbox', name='days[]', value='Mon')
label(for='create-shift-mon') Mon
div.checkbox-inline
input.checkbox-input#create-shift-tue(type='checkbox', name='days[]', value='Tue')
label(for='create-shift-tue') Tue
div.checkbox-inline
input.checkbox-input#create-shift-wed(type='checkbox', name='days[]', value='Wed')
label(for='create-shift-wed') Wed
div.checkbox-inline
input.checkbox-input#create-shift-thur(type='checkbox', name='days[]', value='Thur')
label(for='create-shift-thur') Thur
div.checkbox-inline
input.checkbox-input#create-shift-fri(type='checkbox', name='days[]', value='Fri')
label(for='create-shift-fri') Fri
div.checkbox-inline
input.checkbox-input#create-shift-sat(type='checkbox', name='days[]', value='Sat')
label(for='create-shift-sat') Sat
div.checkbox-inline
input.checkbox-input#create-shift-sun(type='checkbox', name='days[]', value='Sun')
label(for='create-shift-sun') Sun


Why aren't all the selected checkbox values being captured in the form's POST? Why is it only returning a string of the last selected value instead of all the selected values, which is the expected HTML behavior?

If it helps, my Node/Express server is set up to parse content with the lines:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));


According to this W3C Spec, I should just be able to give each checkbox input the same name and they will be parsed as an array of values upon POST (see example 2 in the spec). I have also tried this, which leads to the same behavior as my issue - only the last selected item is returned, and as a string, not an array.

Answer

After some research here is what i found:

This method of passing an array highly depends on the server, how it will understand the data payload, PHP understands this syntax but JSON objects have it quiet differently.

form#create-shift-form(action='/shifts/new', method='post')
  div.form-group
    p Select which days this shift should apply:
      each val, index in ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
        div.checkbox-inline
          input.checkbox-input(type='checkbox', name=`days[${index}]`, value=val, id=`create-shift-${val}`)
          label(for=`create-shift-${val}`)=val

This will payload will be equivalent to something like this:

days[0]=Mon
days[1]=Tue
days[2]=Wed
days[3]=Thur
days[4]=Fri
days[5]=Sat
days[6]=Sun

which is equivalent to this payload in json:

{
   days: ['Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat', 'Sun']
}

Source: https://darobin.github.io/formic/specs/json/

Update:

For future reference: OP figure the issue, the solution (days[${index}]) is correct, however express body parser extended:true uses querystring instead of qs.

With extended:false, the JSON works as expected to behave. The payload becomes "days[0]"="Mon", "day[1]"="Tues", etc.

app.use(bodyParser.urlencoded({ extended: false }); //instead of true