0

Is there a way to get the custom HTML data-* attributes for the selected radio button when you submit a form? The value does not seem to get picked up by serializeArray().

HTML

<form id="preference-form">
<table>
<tr class ="result">
    <td width="100%">{{Title}}</td>
    <td><input type="radio" id="radio-{{Project_No}}-1" data-application="{{Application_ID}}" name="{{Project_ID}}" value="1"></td>
    <td><input type="radio" id="radio-{{Project_No}}-2" data-application="{{Application_ID}}" name="{{Project_ID}}" value="2"></td>
    <td><input type="radio" id="radio-{{Project_No}}-3" data-application="{{Application_ID}}" name="{{Project_ID}}" value="3"></td>
    <td><input type="radio" id="radio-{{Project_No}}-9" data-application="{{Application_ID}}" name="{{Project_ID}}" value="9"></td>
</tr>
</table>
</form>

JavaScript

$("#preference-form).on('submit', function() {
    var data = $(this).serializeArray();
    console.log(data)
});

This outputs the name and value fields, but I can't seem to find a simple answer about the data-* fields. Unfortunately, I need all three pieces of information in order to perform an update on the database record, and from what I understand:

  • Each ID and Value field has to be unique,
  • Each name field has to be identical to group the elements.

I think the tricky part for this is the multiple elements compared to a single element.

TylerH
  • 20,799
  • 66
  • 75
  • 101
artomason
  • 3,625
  • 5
  • 20
  • 43
  • Couldn't you just use a hidden input? – charlietfl Mar 30 '19 at 00:31
  • Note that wrapping a `` in a `
    ` is invalid markup
    – charlietfl Mar 30 '19 at 00:32
  • Perhaps if I knew how to associate that with the inputs. The `` element of my HTML is actually 3 or 4 deep; how would I associate that? Updated the markup. – artomason Mar 30 '19 at 00:32
  • Do you have other form controls other than radio also? Be simple to write own serializer for radios and come up with objects like `[{app:123, name:'foo', value:3}]` – charlietfl Mar 30 '19 at 00:39
  • Another solution is change `name` to include both `Project_ID` and `Application_ID` with a delimiter and parse out the `Application_ID` either server side or before submitting – charlietfl Mar 30 '19 at 00:42
  • I considered your second approach, but I was hoping to find something less hackish. This particular form only has radios – artomason Mar 30 '19 at 00:43
  • The other issue is `Application_ID` might be empty depending on whether this is an update or an insert. – artomason Mar 30 '19 at 00:48
  • 1
    Then I would suggest another data attribute to identify update vs insert also – charlietfl Mar 30 '19 at 00:52

2 Answers2

1

Based on comment that all you have is radios; writing your own serializer is simple.

First I would put the data attribute on the <tr> for less repetition

<tr data-application="{{Application_ID}}">

Then you would do something like:

var data = $(this).find('tr:has(:radio:checked)').map(function(){
   var $row=$(this), radio = $row.find(':radio:checked')[0]
   return {
      app: $row.data('application'),
      name: radio.name,
      value: radio.value
   }
}).get()
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Could you break your code down a little bit. I assume that `$(this)` is the element that was selected when the `submit` action was performed; in my case `$("#preference-form")`, but what about `$row = $(this)`? My `radio` elements are also tucked into `` elements, will this find that regardless? – artomason Mar 30 '19 at 01:14
  • 1
    First `this` is the form...correct. The inner `this` in `map()` is the `` instance – charlietfl Mar 30 '19 at 01:16
  • It keeps throwing `unrecognized expression: tr.has(:radio:checked)` – artomason Mar 30 '19 at 01:19
  • same error just `tr.has(… :radio:checked)` if I understood your last comment right, but this will also break Edge I think. – artomason Mar 30 '19 at 01:26
  • 1
    Works fine here https://jsfiddle.net/vp8d3tc6/. Nothing used here that shouldn't work in Edge or older IE even. Probably work even in IE 7-8 – charlietfl Mar 30 '19 at 01:38
  • Seems I was missing a colon. Thanks for the help! – artomason Mar 30 '19 at 01:47
0

You are missing #

 $('#preference-form').on('submit', function(e) {

Use a hidden input for the data-* attribute values. The following demo sends to a live test server and the response will be displayed in the iframe below.

$('#preference-form').on('submit', function(e) {
  radData(e);
  var data = $(this).serializeArray();
  console.log(data);
});

var radData = e => {
  $(':radio:checked').each(function(e) {
    var dataSet = $(this).data('application');
    $(this).closest('tr').find('.dataSet').val(dataSet);
  });
}
.as-console-wrapper {
  width: 350px;
  min-height: 100%;
  margin-left: 45%;
}

.as-console-row.as-console-row::after {
  content: '';
  padding: 0;
  margin: 0;
  border: 0;
  width: 0;
}

.hide {
  display: none
}
<form id="preference-form" action='https://httpbin.org/post' method='post' target='response'>
  <table width='100%'>
    <tr class="result">
      <td><input type="radio" id="rad1" data-application="rad1" name="rad1" value="1"></td>
      <td><input type="radio" id="rad2" data-application="rad2" name="rad1" value="2"></td>
      <td><input type="radio" id="rad3" data-application="rad3" name="rad1" value="3"></td>
      <td><input type="radio" id="rad9" data-application="rad9" name="rad1" value="9">
      </td>
      <td class='hide'>
        <input class='dataSet' name='dataSet1' type='hidden'>
      </td>
    </tr>

    <tr class="result">
      <td><input type="radio" id="rad4" data-application="rad4" name="rad2" value="4"></td>
      <td><input type="radio" id="rad5" data-application="rad5" name="rad2" value="5"></td>
      <td><input type="radio" id="rad6" data-application="rad6" name="rad2" value="6"></td>
      <td><input type="radio" id="radA" data-application="radA" name="rad2" value="A">
      </td>
      <td class='hide'>
        <input class='dataSet' name='dataSet2' type='hidden'>
      </td>
    </tr>

    <tr class="result">
      <td><input type="radio" id="rad7" data-application="rad7" name="rad3" value="7"></td>
      <td><input type="radio" id="rad8" data-application="rad8" name="rad3" value="8"></td>
      <td><input type="radio" id="radB" data-application="radB" name="rad3" value="B"></td>
      <td><input type="radio" id="radC" data-application="radC" name="rad3" value="C">
      </td>
      <td class='hide'>
        <input class='dataSet' name='dataSet3' type='hidden'>
      </td>
    </tr>
  </table>
  <input type='submit'>

</form>
<iframe name='response'></iframe>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • What about 2 or more rows with radios? The biggest issue I have found with a hidden input is that there is no way to associate the `data-*` field when or than 1 row is displayed. In my case, each row represents an application, and each column represents a preference. – artomason Mar 30 '19 at 01:25
  • Updated with 2 more rows – zer00ne Mar 30 '19 at 01:47