> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Basket functions

> Implement basket functions in WEBSALE: use the BasketItemAdd action to add products from the product box and react to success or error responses.

# Adding a product to the basket

In this example, the product is added to the basket using the `BasketItemAdd` action. The corresponding form is located, for example, in the product box, which can be placed flexibly.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ var $basketAdd = $wsActions.create("BasketItemAdd", tag=$product.id)}}

{{ if $wsActions.current.success and $wsActions.current.name == "BasketItemAdd" }}
   <p>Product successfully added to the basket!</p>
{{ /if }}

{{ if $basketAdd.error }}
   Errors occurred:
   {{ foreach $error in $basketAdd.errors }}
      {{ if $error.text }}
         {{= $error.text }}
      {{ else }}
         {{= $error.code }}
      {{ /if }}
   {{ /foreach }}
{{ /if }}

<form method="post" action="{{= $wsViews.current.url() }}" itemscope itemtype="http://schema.org/Product" class="h-100">
   <input type="hidden" name="wsact" value="{{= $basketAdd.id }}">
   <input type="hidden" name="wscsrf" value="{{= $basketAdd.csrf }}">
   <input type="hidden" name="wstarget" value="{{= $view.url() }}">
   <input type="hidden" name="productId" value="{{= $product.id }}">

   <p>{{= $product.name }}</p>

   <input type="text" name="quantity" value="{{= $basketAdd.params.quantity|ifNull(1) }}">
   <button type="submit">Add to basket</button>
</form>
```

***

# Removing a product from the basket

Using the `BasketItemDelete` action, products can be removed from the basket.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsBasket.items }}
  {{ foreach $cProduct in $wsBasket.items }}
    {{ var $cProductDelete = $wsActions.create("BasketItemDelete", tag = $cProduct.id) }}

    {{ if $basketItemDelete.error }}
      Errors occurred:
      {{ foreach $error in $basketItemDelete.errors }}
        {{ if $error.text }}
          {{= $error.text }}
        {{ else }}
          {{= $error.code }}
        {{ /if }}
      {{ /foreach }}
    {{ /if }}

    <p>{{= $cProduct.product.name }}</p>
    ...
    <form id="wsFormBasketDeleteProductOffcanvas-{{= $cProduct.id }}" action="{{= $wsViews.viewUrl('basket.htm') }}" method="post" ws-ajax-form>
      <input type="hidden" name="wsReplaceIds" value="wsBasketWrapper,wsBasketEntries,wsBasketOffcanvasContent">
      <input type="hidden" name="wscsrf" value="{{= $cProductDelete.csrf }}">
      <input type="hidden" name="wsact" value="{{= $cProductDelete.id }}">
      <input type="hidden" name="wstarget" value="{{= $wsViews.viewUrl('basket.htm') }}">
      <input type="hidden" name="productId" value="{{= $cProduct.product.id }}">
      <input type="hidden" name="basketItemId" value="{{= $cProduct.id }}">
      <button type="submit">Remove from basket</button>
    </form>
  {{ /foreach }}
{{ /if }}
```

***

# Changing the quantity of individual items in the basket

Using the `BasketItemUpdate` action, the quantity of a product in the basket can be changed.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ if $wsBasket.items }}
  {{ foreach $cProduct in $wsBasket.items }}
    <p>{{= $cProduct.product.name }}</p>

    {{ var $basketItemUpdateAction = $wsActions.create("BasketItemUpdate", tag=$basketItem.id) }}
    
    <form method="post" action="{{ $wsViews.viewUrl('basket.htm') }}">
      <input type="hidden" name="wscsrf" value="{{= $basketItemUpdateAction.csrf }}">
      <input type="hidden" name="wsact" value="{{= $basketItemUpdateAction.id }}">
      <input type="hidden" name="wstarget" value="{{= $wsViews.viewUrl('basket.htm') }}">
      <input type="hidden" name="basketItemId" value="{{= $basketItem.id }}">

      <input type="text" name="quantity" value="{{= $basketItem.quantity | preparedFormat('amount') }}" class="quantityUpdate">
    </form>
    
    <script type="text/javascript">
      $("input.quantityUpdate").on("change", function() {
        $(this).closest("form").submit();
      });
    </script>

    {{ if $basketItemUpdateAction.success }}
      <p>Quantity successfully changed.</p>
    {{ /if }}

    {{ if $basketItemUpdateAction.error }}
      Errors occurred:
      {{ foreach $error in $basketItemUpdateAction.errors }}
        {{ if $error.text }}
          {{= $error.text }}
        {{ else }}
          {{= $error.code }}
        {{ /if }}
      {{ /foreach }}
    {{ /if }}
  {{ /foreach }}
{{ /if }}
```

***

# Offcanvas mini basket

The required CSS and JavaScript files are already included in the delivery shop. However, additional scripts are required if the functions to change the quantity and remove a product from the basket are needed.

**Button to open the mini basket**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<button type="button" title="Basket" data-bs-toggle="offcanvas" data-bs-target="#wsBasketOffcanvas">
   <svg role="img" xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="currentColor" viewBox="0 0 16 16"><path d="M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z"/></svg>
   <span id="wsBasketEntries">
      {{ if $wsBasket.items }}
         {{= $wsBasket.items | len }}
      {{ /if }}
   </span>
</button>
```

**Display area of the mini basket**

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<div class="offcanvas offcanvas-end" tabindex="-1" id="wsBasketOffcanvas">
   <div class="offcanvas-header">
      <p>Basket</p>
      <button type="button" data-bs-dismiss="offcanvas" title="Close"></button>
   </div>
   <div class="offcanvas-body">
      <div id="wsBasketOffcanvasContent">
         {{ if $wsBasket.items }}
            <table class="table">
               {{ foreach $cProduct in $wsBasket.items }}
                  <tr>
                     <td class="wsTableCellMin">
                        <a href="{{= $wsViews.url('Product', {productId: $cProduct.product.id}) }}">
                        <img src="{{= $cProduct.product.custom.image.normal}}" alt="Product image for '{{= $cProduct.product.name }}'" width="100" height="110">
                        </a>
                     </td>
                     <td>
                        {{= $cProduct.product.name }} 
                        {{ if $cProduct.product.variantSelection }}
                           <table>
                              <tbody>
                                 {{ foreach $cVarAttr in $cProduct.product.variantSelection | keys }}
                                    <tr>
                                       <td>{{= $cVarAttr}}:</td>
                                       <td>{{= $cProduct.product.variantSelection[$cVarAttr] }}</td>
                                    </tr>
                                 {{ /foreach }}
                              </tbody>
                           </table>
                        {{ /if }}
                        Quantity: {{= int($cProduct.quantity) }} 
                        Unit price: {{= $cProduct.price | currency }} 
                        {{= $cProduct.total | currency }} 
                     </td>
                  </tr>
               {{ /foreach }}
            </table>
            <div class="container-fluid">
               <div class="row">
                  <div class="col">Shipping costs:</div>
                  <div class="col">{{= $wsCheckout.sum.shippingCost | currency }}</div>
               </div>
               <div class="row">
                  <div class="col">Total:</div>
                  <div class="col">{{= $wsBasket.total | currency }}</div>
               </div>
            </div>
            <a href="{{= $wsViews.viewUrl('basket.htm')}}">View basket</a>

            {{ if $wsAccount.isLoggedIn or $wsCheckout.guestMail }}
               <a href="{{= $wsViews.viewUrl('checkout.htm', {step: 1}) }}">Checkout<svg role="img" xmlns="http://www.w3.org/2000/svg" width="20" height="23" fill="currentColor" class="ms-2 align-text-bottom" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/></svg></a>
            {{ else }}
               <a href="{{= $wsViews.viewUrl('account/login.htm', {checkout: true}) }}">Checkout<svg role="img" xmlns="http://www.w3.org/2000/svg" width="20" height="23" fill="currentColor" class="ms-2 align-text-bottom" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/></svg></a>
            {{ /if }}
         {{ else }}
            <p>You have no products in the basket!</p>
         {{ /if }}
      </div>
   </div>
</div>  
```

### Changing quantity and removing products

This requires additional scripts for the corresponding Ajax functions.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<div class="offcanvas offcanvas-end" tabindex="-1" id="wsBasketOffcanvas">
   <div class="offcanvas-header">
      <p>Basket</p>
      <button type="button" data-bs-dismiss="offcanvas" title="Close"></button>
   </div>
   <div class="offcanvas-body">
      <div id="wsBasketOffcanvasContent">
         {{ if $wsBasket.items }}
            <table class="table">
               {{ foreach $cProduct in $wsBasket.items }}
                  {{ var $cProductDelete = $wsActions.create("BasketItemDelete", tag = $cProduct.id) }}
                  {{ var $cProductUpdateAction = $wsActions.create("BasketItemUpdate", tag = $cProduct.id) }}
                  <tr>
                     <td class="wsTableCellMin">
                        <a href="{{= $wsViews.url('Product', {productId: $cProduct.product.id}) }}">
                        <img src="{{= $cProduct.product.custom.image.normal}}" alt="Product image for '{{= $cProduct.product.name }}'" width="100" height="110">
                        </a>
                     </td>
                     <td>
                        {{= $cProduct.product.name }} 
                        {{ if $cProduct.product.variantSelection }}
                           <table>
                              <tbody>
                                 {{ foreach $cVarAttr in $cProduct.product.variantSelection | keys }}
                                    <tr>
                                       <td>{{= $cVarAttr}}:</td>
                                       <td>{{= $cProduct.product.variantSelection[$cVarAttr] }}</td>
                                    </tr>
                                 {{ /foreach }}
                              </tbody>
                           </table>
                        {{ /if }}
                        Quantity: {{= int($cProduct.quantity) }} 
                        Unit price: {{= $cProduct.price | currency }} 
                        {{= $cProduct.total | currency }} 
                        <form id="wsFormBasketQuantityChangeOffcanvas-{{= $cProduct.id }}" action="{{= $wsViews.current.url() }}" method="post" ws-ajax-form>
                           <input type="hidden" name="wsReplaceIds" value="wsBasketWrapper,wsBasketEntries,wsBasketOffcanvasContent">
                           <input type="hidden" name="wscsrf" value="{{= $cProductUpdateAction.csrf }}">
                           <input type="hidden" name="wsact" value="{{= $cProductUpdateAction.id }}">
                           <input type="hidden" name="wstarget" value="{{= $wsViews.current.url() }}">
                           <input type="hidden" name="basketItemId" value="{{= $cProduct.id }}">
                           <div class="wsBasketQuantityChange" role="group">
                              <button type="button" title="Decrease quantity by 1" ws-operator="minus"><svg role="img" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="mb-1" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M2 8a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11A.5.5 0 0 1 2 8Z"/></svg></button>
                              <input type="text" name="quantity" value="{{= $cProduct.quantity | preparedFormat('amount') }}" class="wsBasketQuantityChangeInput form-control text-center rounded-0 border-0 mx-1" aria-label="Quantity">
                              <button type="button" title="Increase quantity by 1" ws-operator="plus"><svg role="img" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="mb-1" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2Z"/></svg></button>
                           </div>
                        </form>
                        <form id="wsFormBasketDeleteProductOffcanvas-{{= $cProduct.id }}" action="{{= $wsViews.viewUrl('basket.htm') }}" method="post" ws-ajax-form>
                           <input type="hidden" name="wsReplaceIds" value="wsBasketWrapper,wsBasketEntries,wsBasketOffcanvasContent">
                           <input type="hidden" name="wscsrf" value="{{= $cProductDelete.csrf }}">
                           <input type="hidden" name="wsact" value="{{= $cProductDelete.id }}">
                           <input type="hidden" name="wstarget" value="{{= $wsViews.viewUrl('basket.htm') }}">
                           <input type="hidden" name="productId" value="{{= $cProduct.product.id }}">
                           <input type="hidden" name="basketItemId" value="{{= $cProduct.id }}">
                           <button type="submit">
                              <svg role="img" xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="currentColor" viewBox="0 0 16 16">
                                 <path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5ZM11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H2.506a.58.58 0 0 0-.01 0H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1h-.995a.59.59 0 0 0-.01 0H11Zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5h9.916Zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47ZM8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5Z"/>
                              </svg>
                              Delete
                           </button>
                        </form>
                     </td>
                  </tr>
               {{ /foreach }}
            </table>
            <div class="container-fluid">
               <div class="row">
                  <div class="col">Shipping costs:</div>
                  <div class="col">{{= $wsCheckout.sum.shippingCost | currency }}</div>
               </div>
               <div class="row">
                  <div class="col">Total:</div>
                  <div class="col">{{= $wsBasket.total | currency }}</div>
               </div>
            </div>
            <a href="{{= $wsViews.viewUrl('basket.htm')}}">View basket</a>

            {{ if $wsAccount.isLoggedIn or $wsCheckout.guestMail }}
               <a href="{{= $wsViews.viewUrl('checkout.htm', {step: 1}) }}">Checkout<svg role="img" xmlns="http://www.w3.org/2000/svg" width="20" height="23" fill="currentColor" class="ms-2 align-text-bottom" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/></svg></a>
            {{ else }}
               <a href="{{= $wsViews.viewUrl('account/login.htm', {checkout: true}) }}">Checkout<svg role="img" xmlns="http://www.w3.org/2000/svg" width="20" height="23" fill="currentColor" class="ms-2 align-text-bottom" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/></svg></a>
            {{ /if }}

            {{# crosslinks #}}
            {{ foreach $cProduct in $wsBasket.items }}
               {{ if $cProduct.product.custom.crosslinks }}
                  <p>Goes well with this</p>
                  <div class="row">
                     {{ var $cCrosslinks = $cProduct.product.custom.crosslinks | split(",") | take(2) }}
                     {{ foreach $cCrosslinkProduct in $cCrosslinks }}
                        {{ var $cCrosslinkProductInfo = $wsProducts.load($cCrosslinkProduct) }}
                        <div class="col-6">
                           {{ include "components/product/productBox.htm" with $cProduct = $cCrosslinkProductInfo }}
                        </div>
                     {{ /foreach }}
                  </div>
               {{ /if }}
            {{ /foreach }}
         {{ else }}
            <p>You have no products in the basket!</p>
         {{ /if }}
      </div>
   </div>
</div>  
```


## Related topics

- [$wsBasket - Basket](/en/frontend/referenz/module/wsbasket.md)
- [Functions](/en/frontend/referenz/funktionen.md)
- [basket - Basket](/en/konfiguration/basket-warenkorb.md)
- [Basket](/en/frontend/referenz/aktionen/basket.md)
- [actions - Basket & checkout](/en/konfiguration/actions-fehlertexte-e-mails/actions-warenkorb-checkout.md)
