1

First off, I'd like to thank Jeremy for his help.

I have a set of add-on products that go along with my primary product. The options are a radio group.

I am using Multi-Add to tie everything together - and it's all working great. I'm able to add the primary and optional products to the cart.

Where I am hung up is, because I have a radio group - no matter which option I choose, I am always ending up with the last option being chosen. Which makes perfect sense since that's the last radio in the group that gets picked up.

Here is what I have so far:

...
// items[1][qty] is a <select> input for the primary product
...

{% for foo in products %}
    <div class="radio">
        <label>
            <input type="radio" name="items[2][qty]" value="1">
               {{ foo.title }} &ndash; {% if foo.defaultVariant.price == 0 %} Included with registration {% else %} {{ foo.defaultVariant.price|currency(cart.currency) }}{% endif %}
        </label>
        <input type="hidden" name="items[2][purchasableId]" value="{{ foo.defaultVariant.purchasableId }}">
    </div>
{% endfor %}

As you can see whatever the last radio input is, will be the value that is picked up by Craft regardless of what the user has actually chosen.

So I thought since each radio is a product (with no variants), I could just use the loop index:

<input type="hidden" name="items[{{ loop.index }}][purchasableId]" value="{{ foo.defaultVariant.purchasableId }}">

Which works, but the loop will start at 1 each time. I am hung up on how I can start the loop at a specific number. Or, perhaps there is a better way?

If I were using checkboxes, I'd only have one option per product/input name.

I have also tried using a <select> element, but I get hung up on how I can offer a "No thanks" option.

<select name="items[2][purchasableId]" class="form-control required">
    <option value="">Select</option>
     {% for foo in products %}
         <option value="{{ foo.defaultVariant.purchasableId }}">
         {{ foo.title }} &ndash; {% if foo.defaultVariant.price == 0 %} Included with registration {% else %} {{ foo.defaultVariant.price|currency(cart.currency) }}{% endif %}
         </option>
    {% endfor %}
</select>
<input type="hidden" name="items[2][qty]" value="1">

Which also works well, but if the user does not choose an option, because I am passing a value of 1 with the hidden input, I get an error that I am attempting to use an invalid purchasable ID. Which also makes perfect sense.

I feel like I am so close, but just can't quite see clear enough to know what to do. Worst case I suppose I just listen for either a change/click event via javascript and update the qty value accordingly.

Thank you for any suggestions!

1

You definitely don't need JS here.

I'm a bit pushed for time, so this won't be an epic answer, but e.g. with your select, you should not be using a hidden field for the qty.

The select itself just sets the quantity value - either 1 if the option is chosen or no value if the option is not chosen....it really is as simple as:

<form>

  {# primary item - use whatever input you like for qty, or just do it in a hidden... #}
  <input type="hidden" name="items[9999][purchasableId" value="{{ mainproduct.purchasableId }}">
  <input type="hidden" name="items[9999][qty]" value="1">

  {# accessories #}
  {% for accessory in accessories %}
    <input type="hidden" name="items[loop.index][puchasableId]" value=="{{ accessory.purchasableId }}"
    <select name="items[loop.index][qty]">
      <option value="1">Yes Please</option>
      <option value="0">No Thanks</option>
    </select> 
  {% endfor %}

</form>

This will cause the following to be posted - items[0][purchasableId] = 45

and depending on the user choice, either

items[0][qty] = 1 or items[0][qty] = 0

...and multiAdd will just ignore this if the qty = 0.

The key thing to understand is the value of the index is totally irrelevant as long as it is the same for the purchasableId and the qty - it just acts to join the data together - you could literally send:

items['TrumpIsInsane'][purchasableId] = 45
items['TrumpIsInsane'][qty] = 1

...and it should still work. So for the primary product I just use something like 9999 so that I am sure it won't conflict with any of the loop indexes (I'm not going to have 10000 accessories eh?) -> it's just a made up number.

For completeness, radios would only be slightly different:

<form>

  {# primary item - use whatever input you like for qty, or just do it in a hidden... #}
  <input type="hidden" name="items[9999][purchasableId" value="{{ mainproduct.purchasableId }}">
  <input type="hidden" name="items[9999][qty]" value="1">

  {# accessories #}
  {% for accessory in accessories %}
    <input type="hidden" name="items[loop.index][puchasableId]" value=="{{ accessory.purchasableId }}"
    <input type="radio" name="items[loop.index][qty]" value="1" checked> Yes Please<br>
    <input type="radio" name="items[loop.index][qty]" value=""> No Thanks<br>
  {% endfor %}
</form> 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.