9

I am aiming to create a form to handle disabled JavaScript experience for a small component on my website. Currently I have the following form:

<form method="GET" action="https://mywebsite.com/somedirectory/">

    <input type="radio" id="uid1" name="someParam" value="fruity" />
    <label for="uid1">Fruit</label>

    <input type="radio" id="uid2" name="someParam" value="veggie" />
    <label for="uid2">Vegetable</label>

    ...other radio options

    <input type="submit" value="Submit" />
</form>

Clicking on either of the radio options and then on the submit button will result in:

option 1: https://mywebsite.com/somedirectory/?someParam=fruity
option 2: https://mywebsite.com/somedirectory/?someParam=veggie

How can I add another value for each of the radio options? Say I would like to pass someOtherParam which is unique for each option and I would like to get this as output for my options:

option 1: https://mywebsite.com/somedirectory/?someParam=fruity&someOtherParam=apple
option 2: https://mywebsite.com/somedirectory/?someParam=veggie&someOtherParam=pepper

What I have tried is:

<input type="radio" id="uid1" name="someParam" value="fruity&someOtherParam=apple" />
<input type="radio" id="uid2" name="someParam" value="veggie&someOtherParam=pepper" />

However, the & symbol is converted to %26 inside the link and feels too hacky. Is there a better way to achieve this? Also, is there a way to make sure the Submit button is only enabled once a radio option is selected?

P.S. I am aiming for pure HTML experience with no Javascript involved. Is that possible?

EDJ
  • 843
  • 3
  • 17
  • 37

7 Answers7

6

I'm pretty sure this is not posible in modern browsers without the use of JS. Maybe on old browsers you could do some tricks with CSS and display:none because it used to not send fields with display:none, but nowdays that is not an option.

If you can allow Javascript, you can add a data attribute to each radio option and use it to populate an extra hidden input on change.

document.querySelectorAll('input[type=radio][name="someParam"]')
  .forEach(radio => radio.addEventListener('change', (event) =>
    document.getElementById('someOtherParam').value = event.target.dataset.extraValue
  ));
<form method="GET" action="https://mywebsite.com/somedirectory/">
  <input type="radio" id="uid1" name="someParam" value="fruity" data-extra-value="apple" />
  <label for="uid1">Fruit</label>

  <input type="radio" id="uid2" name="someParam" value="veggie" data-extra-value="pepper" />
  <label for="uid2">Vegetable</label>

  <input type="hidden" id="someOtherParam" name="someOtherParam">

  <input type="submit" value="Submit" />
</form>
Alvaro Flaño Larrondo
  • 5,516
  • 2
  • 27
  • 46
0

To add another radio group independent from others, use a distinct name property. For example, to add a second parameter called someOtherParam to the request, create a radio group with name="someOtherParam":

<input type="radio" id="uid3" name="someOtherParam" value="apple" />
<input type="radio" id="uid4" name="someOtherParam" value="pepper" />

And add their correspondent labels.

Also, is there a way to make sure the Submit button is only enabled once a radio option is selected?

You can add the required attribute to prevent the browser to send the form before all the inputs have a value.

  • 1
    But this would just add two more radio options to the list. Instead, what I wanted to achieve is that whenever the option with value “fruit” is selected someOtherParam is added as well for it and the whole link now has two total params for this radio option. (E.g ‘someParam=fruit&someOtherParam=apple’ for radio option 1 and ‘someParam=veggie&someOtherParam=pepper’ for radio option 2. – EDJ Jan 01 '21 at 18:07
  • As Rahul notes, there's no way to do that without javascript. Please update your post to clarify what you want – Manuel Alcaraz Jan 02 '21 at 14:54
0

Without javascript, what you're describing cannot be done.

What you could do, as other posters have suggested is:

Create radio buttons for the list of options that are possible for each category (fruits / vegetables etc)

<input type="radio" id="uid3" name="someOtherParam" value="apple" />
<input type="radio" id="uid4" name="someOtherParam" value="pepper" />

When processing the input on your server side code, check if you have received a value or not. If not, you can choose a default option (apple or whatever). On your page you can mention what the default option would be in case they don't make a selection.

You could make some of the input required as suggested, but you would still have to make check on the server side that the input has been received, since the required attribute is just a suggestion to users browsers - it won't stop a malicious persons from making a request without that parameter by running a script etc.

Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
  • you mentioned what I wanted cannot be achieved without javascript. Do you mind updating how this can be achieved with JavaScript? – EDJ Jan 06 '21 at 16:25
0

Easy, double up the value with a deliminator between every extra value:

HTML

<div>
<label for="uid1">
<input id="uid1" name="fruit1" type="radio" value="apple:orange" />
Fruit, Apple + Orange
</label>
</div>


<div>
<label for="uid2">
<input id="uid2" name="fruit1" type="radio" value="apple:cherry:lime" />
Fruit, Apple + Cherry + Lime
</label>
</div>

node.js

I'm not sure how node.js handles what PHP refers simply as $_POST['name_attribute_value_here'] though I do know you simply want to use .split(':') to get the two or more values from that single form. If you want more options per radio button just append a deliminator (it doesn't have to be :) between each value.

  • Both of those radio options have the name "fruit1" so the user can't choose both.
  • No JavaScript is necessary.
  • A minor adaptation on the server.
  • Extra values will obviously not appear to the server if the user doesn't select that radio form field.

Arrays

If you want to set your own key/values then just add a second deliminator:

<input name="fruit1" value="fruit:apple,fruit:lime,color:purple,planet:Earth" />

Then at the server use [whatever].split(',') to get the pairs and iterate in a loop to get each key/value. You could create an entire crazy multi-dimensional array if you really wanted to.

I hope this helps, feel free to comment if you need any further clarification.

John
  • 1
  • 13
  • 98
  • 177
0

To submit extra information to the server, you can use a hidden input type and change value as per your needs using javascript.

HTML code

<form method="GET" action="">

    <input type="radio" id="uid1" name="someParam" value="fruity" />
    <label for="uid1">Fruit</label>

    <input type="radio" id="uid2" name="someParam" value="veggie" />
    <label for="uid2">Vegetable</label>

    <input type="hidden" id="uid3" name="someOtherParam" value="" readonly required />

    <input type="submit" value="Submit" onclick="onSubmit()" />
</form>

Javascript code

function onSubmit () {
    let fruityRadio = document.getElementById( 'uid1' );
    let veggieRadio = document.getElementById( 'uid2' );
    if ( fruityRadio.checked ) {
        document.getElementById( 'uid3' ).value = 'apple';
    } else if ( veggieRadio.checked ) {
        document.getElementById( 'uid3' ).value = 'pepper';
    }
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

Generate form:

const data = [
  { name: 'apple', type:"fruity" },
  { name: 'pepper', type:"veggie"}
]

const form = document.querySelector('form');
const uid = document.querySelector('#uid')
createOptions(data);

function createOptions(data){
  data.forEach((e, index) => {
    const f = document.createDocumentFragment();
    const l = document.createElement('label');
    const i = document.createElement('input');
    l.setAttribute('for', `uid${index+1}`);
    l.textContent=e.name;
    i.setAttribute('type', `radio`);
    i.setAttribute('for', `uid${index+1}`);
    i.setAttribute('name', 'someOtherParam');
    i.setAttribute('value', e.name);
    i.dataset.otype = e.type;
    f.appendChild(l);
    f.appendChild(i);
    form.insertBefore(f, uid);
    i.addEventListener('change', onselectChange, false);
  })  
}

function onselectChange(event) {
  uid.value = event.target.dataset.otype;
}
<form method="GET" action="https://mywebsite.com/somedirectory/">
  <input type="text" id="uid" name="someParam"
    style="width:0; visibility: hidden;">
  <input type="submit" value="Submit" />
</form>
Daniil Loban
  • 4,165
  • 1
  • 14
  • 20
0

I can't think another way of doing this using less code, the following achieves your desired result:

<form name="form" method="GET" action="">
    <input type="radio" id="uid1" name="someParam" required value="fruity" onchange="document.form.someOtherParam.value = 'apple'" />
    <label for="uid1">Fruit</label>
    <input type="radio" id="uid2" name="someParam" required value="veggie" onchange="document.form.someOtherParam.value = 'pepper'" />
    <label for="uid2">Vegetable</label>
    <input type="hidden" name="someOtherParam" value=""/>
    <input type="submit" value="Submit"/>
</form>
There's only 3 changes to your example:
  1. Add a name to the form
  2. Add inline attributes required and onchange to each radio
  3. Add an input[type=hidden] to include the extra param.

The first change is meant so you'll not need document.getElementById later, the second so the form won't be empty submitted and also update the hidden desired value.

luiscla27
  • 4,956
  • 37
  • 49