This is the documentation for LemonStand V1, which has been discontinued. You can learn more and upgrade your store here.

LemonStand Version 1 Has Been Discontinued

This documentation is for LemonStand Version 1. LemonStand is now offered as a cloud-based eCommerce platform.
You can try the new LemonStand and learn about upgrading here.

Displaying Bundle Items in the Shopping Cart

Required: Ensure you complete the guide on Displaying a List in your Shopping Cart before you continue.

There are different ways to represent bundle products in the cart. For example, if your base bundle product has no price and its price is a sum of bundle items, then you can display the total product bundle price right in the base product row. Another way to display the total bundle price is a separate line in the cart table. This option is more universal, and its implementation is described in this section. This approach is implemented in our Simplicity theme:

In general the process if displaying bundle items in the cart is similar to the process described above, but there are a number of significant differences:

  1. Required bundle items cannot be removed from the cart, so  Delete link should be hidden.
  2. Some bundle items do not allow manual quantity input, so Quantity field should be hidden and replaced with a static text. Also, you should use cart item's get_quantity() method to display the item quantity instead of the $quantity field. get_quantity() method correctly calculates the item item quantity in bundle. For example, imagine that your base product is a PC and it has a bundle item RAM which quantity is 1. If the user sets quantity 2 for the PC, this will mean that the total quantity is RAM is 2, but there will be still 1 RAM per 1 PC. get_quantity() method will return 1 in this case (meaning 1 RAM item per each PC product), while $quantity field will return 2 (the total quantity value for RAM in the order). 
  3. Bundle items cannot be postponed separately from the base bundle product, so the Postpone checkbox should not be visible.
  4. Value in the total column for bundle items should display the total price per single master product. Optionally you can display the multiplier value (see the code snippet below).

Updating the cart partial to display bundle items

The following code represents the updated cart table body for displaying bundle items:

<?
  $last_index = count($items)-1;

  foreach ($items as $index=>$item):
  $image_url = $item->product->image_url(0, 60, 'auto');
  $options_str = $item->options_str();
  
  // Load item bundle item and bundle item product objects
  $bundle_item = $item->get_bundle_item();
  $bundle_item_product = $item->get_bundle_item_product();
  
?>
  <tr>
    <td>
      <? if ($image_url): ?>
        <img src="<?= $image_url ?>" alt="<?= h($item->product->name) ?>"/>
      <? endif ?>
      <strong><?= h($item->product->name) ?></strong>
      <? if (strlen($options_str)): ?>
        <br/><?= h($options_str) ?>.
      <? endif ?>
      <? if ($item->extra_options): ?>
        <? foreach ($item->extra_options as $option): ?>
          <br/>
          + <?= h($option->description) ?>:
          <?= format_currency($option->get_price($item->product)) ?>
        <? endforeach ?>
      <? endif ?>
    </td>
    <td>
      <!-- Do not display the Postpone checkbox for bundle items -->
      <? if (!$bundle_item_product): ?>
        <input type="hidden" name="item_postponed[<?= $item->key ?>]" value="0"/>
        <input 
          type="checkbox" 
          <?= checkbox_state($item->postponed) ?> name="item_postponed[<?= $item->key ?>]" value="1"/>
      <? endif  ?>
    </td>
    <td>
      <!-- Do not display the Delete checkbox for required bundle items -->
      <? if (!$bundle_item || !$bundle_item->is_required): ?>
        <input type="checkbox" name="delete_item[]" value="<?= $item->key ?>"/>
      <? endif  ?>
    </td>
    <td>
      <!-- Do not display the Quantity field for postponed items and 
           bundle items which do not allow manual quantity input -->
      <? if (!$postponed && (!$bundle_item_product || $bundle_item_product->allow_manual_quantity)): ?>
        <input type="text" name="item_quantity[<?= $item->key ?>]" value="<?= $item->get_quantity() ?>"/>
      <? else: ?>
        <?= $item->get_quantity() ?>
      <? endif ?>
    </td>
    <td><?= format_currency($item->single_price()) ?></td>
    <td><?= format_currency($item->total_discount()) ?></td>
    <th>
      <? if (!$item->is_bundle_item()): ?>
        <?= format_currency($item->total_price()) ?>
      <? else:
        // For bundle items use the bundle_item_total_price() method to get 
        // the total item price per single base product
        // and display the multiplier.
        $master_item = $item->get_master_bundle_item();
        $multiplier = ($master_item && $master_item->quantity > 1) ? ' x '.$master_item->quantity : null;
      ?>
        <?= format_currency($item->bundle_item_total_price()).$multiplier ?>
      <? endif  ?>
    </th>
  </tr>
  
  <!-- Display the bundle total row -->
  
  <? 
    if (
          ($bundle_item && $index == $last_index) 
          || ($bundle_item && $bundle_item->id && !$items[$index+1]->get_bundle_item())): 
      $master_item = $item->get_master_bundle_item();
      if ($master_item):
  ?>
      <tr>
        <td colspan="3"><?= h($master_item->product->name) ?> bundle totals</td>
        <td><?= $master_item->quantity ?></td>
        <td><?= format_currency($master_item->bundle_single_price()) ?></td>
        <td><?= format_currency($master_item->bundle_total_discount()) ?></td>
        <th><?= format_currency($master_item->bundle_total_price()) ?></th>
      </tr>
  <? 
      endif;
    endif ?>  
<? endforeach ?>
{% set last_index = items|length-1 %}
{% for index, item in items %}
  {% set image_url = item.product.image_url(0, 60, 'auto') %}
  {% set options_str = item.options_str() %}
  
  {# Load item bundle item and bundle item product objects #}
  {% set bundle_item = item.get_bundle_item() %}
  {% set bundle_item_product = item.get_bundle_item_product()  %}
  <tr>
    <td>
      {% if image_url is not empty %}
        <img src="{{ image_url }}" alt="{{ item.product.name }}"/>
      {% endif %}
      
      <strong>{{ item.product.name }}</strong>
      {% if options_str|length > 0 %}
        <br/>{{ options_str }}.
      {% endif %}
      
      {% if item.extra_options|length > 0 %}
        {% for option in item.extra_options %}
          <br/>
          + {{ option.description }}:
            {{ option.get_price(item.product)|currency }}
        {% endfor %}
      {% endif %}
    </td>
    <td>
      <!-- Do not display the Postpone checkbox for bundle items -->
      {% if not bundle_item_product %}
        <input type="hidden" name="item_postponed[{{ item.key }}]" value="0"/>
        <input type="checkbox" {{ checkbox_state(item.postponed) }} name="item_postponed[{{ item.key }}]" value="1"/>
      {% endif %}
    </td>
    <td>
      <!-- Do not display the Quantity field for postponed items and 
          bundle items which do not allow manual quantity input -->
      {% if not postponed or (not bundle_item_product or bundle_item_product.allow_manual_quantity) %}
        <input type="text" name="item_quantity[{{ item.key }}]" value="{{ item.quantity }}"/>
      {% else %}
        {{ item.quantity }}
      {% endif %}
    </td>
    <td>
      <!-- Do not display the Delete checkbox for required bundle items -->
      {% if not bundle_item or not bundle_item.is_required %}
        <input type="checkbox" name="delete_item[]" value="<?= $item->key ?>"/>
      {% endif %}
    </td>
    <td>
      {% if not item.is_bundle_item() %}
        {{ item.total_price()|currency }}
      {% else %}
        {#
          For bundle items use the bundle_item_total_price() method to get 
          the total item price per single base product
          and display the multiplier.
        #}
        {% set master_item = item.get_master_bundle_item() %}
        {% set multiplier = (master_item and master_item.quantity > 1) ? ' x '~master_item.quantity : null %}
        {{ item.bundle_item_total_price()|currency~multiplier }}
      {% endif %}
    </td>
    <td>{{ item.total_discount()|currency }}</td>
    <th>{{ item.total_price()|currency }}</th>
  </tr>
  
  <!-- Display the bundle total row -->
  {% if 
    (bundle_item and index == last_index) or 
    (bundle_item and bundle_item.id and 
      not attribute(items, index+1).get_bundle_item()) %}
      
    {% set master_item = item.get_master_bundle_item() %}
    {% if master_item %}
      <tr>
        <td colspan="3">{{ master_item.product.name }} bundle totals</td>
        <td>{{ master_item.quantity }}</td>
        <td>{{ master_item.bundle_single_price()|currency }}</td>
        <td>{{ master_item.bundle_total_discount()|currency }}</td>
        <th>{{ master_item.bundle_total_price()|currency }}</th>
      </tr>
    {% endif %}
  {% endif %}
{% endfor %}

Next: Displaying a List of Shopping Cart Items
Previous: Creating a Checkout Button with a Coupon Field
Return to Shopping Cart