点击加入购物车按钮,实现加入购物车

{{#capture "default_variant_id"}}
            {{default product.selected_or_first_available_variant.id (get "id" (first product.variants))}}
{{/capture}}
        
  <script src="{{asset_url 'component-product-form.js'}}" defer="defer"></script>
  <div class="article-template__right-Products">
            <h1>Products from the article</h1>
              {{#if article.metafields.is_show_product.is_show_product.value}}
              {{#each section.blocks as |block|}}
             {{#if block.type == "product_picker_myself"}}
            <div>
             
               
                <div class="product-art-right-box">
                    <a href="{{block.settings.product_id.url}}">
                    <div class="product-image-right-box">
                        <img src="{{block.settings.product_id.featured_image}}" alt="Product Image">
                        <div class="product-right-favorite-icon" onclick="toggleFavorite()">❤</div>
                    </div>
                    {{#if block.settings.product_id.available}}
                        <div class="product-right-sale-status">Sale</div>
                    {{else}}
                        <div class=" product-right-sale-status-out">Sold out</div>
                    {{/if}}

                    <div class="product-right-product-title">{{block.settings.product_id.title}}</div>
                    <div class="product-right-product-description">{{{block.settings.product_id.description}}}</div>
                    <div class="product-right-reviews">
                        <div class="product-right-stars">★★★★★</div>
                        <div class="product-right-review-count">6 Reviews</div>
                    </div>
                    </a>
                    <div class="product-right-cart-module">
                        <div class="product-right-prices">
                            <div class="product-right-original-price">{{money block.settings.product_id.compare_at_price_max}}</div>
                            <div class="product-right-current-price">{{money block.settings.product_id.price}}</div>
                        </div>
                        
                        {{!-- <button class="product-right-cart-button">
               <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="product-right-cart-icon">
  <path d="M7 4h-2l-3 9v1c0 1.1.9 2 2 2h14v-2H4.4l1.1-3H16c.6 0 1.1-.4 1.2-.9l1.8-8.1H4.2l-.2-.8zM7 18c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
                         </button> --}}
                         <div>
                              {{assign "product_form_id" block.settings.product_id.id}}
                             <product-form
                    id="{{append product_form_id '__wrapper'}}"
                        class="product-form"
                        data-default-error-message="{{t 'products.general.no_product_data_found'}}"
                        >
                    <form method="post" action="/api/carts/ajax-cart/add.js" id="productFrom" id={{product_form_id}}>
                     <input type="number" required step="1" form="product-form-{{section.id}}" name="quantity" min='1' max='999' value='1'/ hidden>
                            <input type="hidden" name="id" value="{{default block.settings.product_id.selected_or_first_available_variant.id (get 'id' (first block.settings.product_id.variants))}}" disabled  class="ids"/>
                    <button class="product-right-cart-button" type="submit"  name="add"  id="{{product_form_id}}-submit">
                        {{snippet "carticon"}}
                    </button>
                    <div class="loading-overlay__spinner ">
                        <svg class="icon icon-loading" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M18.3337 9.99984C18.3337 14.6022 14.6027 18.3332 10.0003 18.3332C5.39795 18.3332 1.66699 14.6022 1.66699 9.99984C1.66699 5.39746 5.39795 1.6665 10.0003 1.6665" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"></path>
                        </svg>

                        </div>
                      </form>
                    </product-form>
                         </div>




                    </div>
                </div>

            </div>
              {{/if}}
              {{/each}}
            {{/if}}
        </div>
按钮:
      <div>
                              {{assign "product_form_id" block.settings.product_id.id}}
                             <product-form
                    id="{{append product_form_id '__wrapper'}}"
                        class="product-form"
                        data-default-error-message="{{t 'products.general.no_product_data_found'}}"
                        >
                    <form method="post" action="/api/carts/ajax-cart/add.js" id="productFrom" id={{product_form_id}}>
                     <input type="number" required step="1" form="product-form-{{section.id}}" name="quantity" min='1' max='999' value='1'/ hidden>
                            <input type="hidden" name="id" value="{{default block.settings.product_id.selected_or_first_available_variant.id (get 'id' (first block.settings.product_id.variants))}}" disabled  class="ids"/>
                    <button class="product-right-cart-button" type="submit"  name="add"  id="{{product_form_id}}-submit">
                        {{snippet "carticon"}}
                    </button>
                    <div class="loading-overlay__spinner ">
                        <svg class="icon icon-loading" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M18.3337 9.99984C18.3337 14.6022 14.6027 18.3332 10.0003 18.3332C5.39795 18.3332 1.66699 14.6022 1.66699 9.99984C1.66699 5.39746 5.39795 1.6665 10.0003 1.6665" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"></path>
                        </svg>

                        </div>
                      </form>
                    </product-form>
                         </div>
js代码:
defineCustomElement('product-form', () => {
  return class ProductForm extends HTMLElement {
    constructor() {
      super();

      this.form = this.querySelector('form');
      if (!this.form) {
        return;
      }

      this.options = {
        onErrorShowToast: this.dataset.onErrorShowToast || false,
      };

      this.fetchInstance = Promise.resolve();
      this.form.querySelector('[name=id]').disabled = false;
      this.cart = document.querySelector('cart-notification') || document.querySelector('cart-drawer-entry');
      this.submitButton = this.querySelector('[type="submit"]');
      this.submitButton.addEventListener('click', this.submitButtonClickHandler.bind(this));
    }

    // Because the editor hijack the a tag click event, the click event needs to be bound to prevent bubbling
    submitButtonClickHandler(e) {
      e.preventDefault();
      e.stopPropagation();
      this.onSubmitHandler();
    }

    onSubmitHandler() {
      if (this.submitButton.classList.contains('disabled') || this.submitButton.classList.contains('loading')) {
        return;
      }
      const formData = new FormData(this.form);
      const currentVariantId = formData.get('id');
      if (!currentVariantId) {
        window.Shopline.utils.toast.open({
          duration: 2000,
          content: t('products.product_list.select_product_all_options'),
        });
        return;
      }
      this.handleErrorMessage();

      this.submitButton.classList.add('loading');
      this.querySelector('.loading-overlay__spinner').classList.add('display-flex');

      const config = window.fetchConfig();
      config.headers['X-Requested-With'] = 'XMLHttpRequest';
      delete config.headers['Content-Type'];
      this.ensureQuantity(formData);
      formData.delete('returnTo');

      const isCartPage = document.body.getAttribute('data-template') === 'cart';
      if (this.cart && !isCartPage) {
        formData.append(
          'sections',
          this.cart.getSectionsToRender().map((section) => section.id),
        );
        formData.append('sections_url', window.location.pathname);
      }
      config.body = formData;
      const fetchInstance = fetch(`${window.routes.cart_add_url}`, config).then((response) => response.json());
      this.fetchInstance = fetchInstance;
      fetchInstance
        .then((response) => {
          if (response.message) {
            this.handleErrorMessage(response.message);
            const isQuickAdd = this.submitButton.classList.contains('quick-add__submit');
            if (!isQuickAdd) return response;
            this.submitButton.classList.add('disabled');
            this.submitButton.querySelector('span').classList.add('hidden');
            this.error = true;
            return response;
          }
          if (!this.cart || isCartPage) {
            window.location = window.routes.cart_url;
            return response;
          }

          this.error = false;
          const quickAddModal = this.closest('quick-add-modal');
          const SLQuickAddModal = (window.Shopline.utils || {}).quickAddModal;
          if (quickAddModal) {
            document.body.addEventListener(
              'modalClosed',
              () => {
                setTimeout(() => {
                  this.cart.renderContents(response);
                });
              },
              { once: true },
            );
            quickAddModal.close(true);
          } else if (SLQuickAddModal) {
            SLQuickAddModal.close().then(() => this.cart.renderContents(response));
          } else {
            this.cart.renderContents(response);
          }
          return response;
        })
        .catch((err) => {
          console.error('product form err', err);
          this.handleErrorMessage(this.getAttribute('data-default-error-message'));
        })
        .finally((response) => {
          this.submitButton.classList.remove('loading');
          this.querySelector('.loading-overlay__spinner').classList.remove('display-flex');
          return response;
        });
    }

    ensureQuantity(formData) {
      if (!formData.has('quantity')) {
        formData.set('quantity', '1');
      }
    }

    handleErrorMessage(errorMessage = false) {
      if (this.options.onErrorShowToast && errorMessage) {
        window.Shopline.utils.toast.open({
          content: errorMessage,
        });
      }
      this.errorMessageWrapper = this.errorMessageWrapper || this.querySelector('.product-form__error-message-wrapper');
      if (!this.errorMessageWrapper) return;
      this.errorMessage = this.errorMessage || this.errorMessageWrapper.querySelector('.product-form__error-message');

      this.errorMessageWrapper.toggleAttribute('hidden', !errorMessage);

      if (errorMessage) {
        this.errorMessage.textContent = errorMessage;
      }
    }
  };
});

window.Shopline.loadFeatures(
  [
    {
      name: 'component-toast',
      version: '0.1',
    },
  ],
  function (error) {
    if (error) {
      throw error;
    }
  },
);

JavaWeb中,可以使用Session来实现加入购物车的功能。下面是一个简单的示例代码来演示如何使用Session实现加入购物车的功能: 1. 首先,在购物车页面上,添加一个“加入购物车”的按钮或链接,点击按钮时触发一个处理函数。 2. 在处理函数中,获取要添加到购物车的商品信息。可以通过表单提交或Ajax等方式将商品信息传递给后台。 3. 在后台处理函数中,首先获取当前用户的Session对象。可以通过request.getSession()方法获取。 4. 判断Session中是否已经存在购物车对象。可以通过getSession().getAttribute("cart")方法获取购物车对象,如果为null,则说明购物车为空,需要创建一个新的购物车对象。 5. 将当前要添加的商品信息添加到购物车对象中,可以将商品信息封装成一个CartItem对象,包含商品ID、名称、价格等信息。 6. 将购物车对象存储到Session中,可以通过getSession().setAttribute("cart", cart)方法将购物车对象存储到Session中。 7. 返回给前台一个添加成功的提示信息,可以使用Ajax方式实现。 8. 在购物车页面中,可以通过Session中存储的购物车对象,将购物车中的商品信息展示出来。 以上就是使用Session实现加入购物车的基本步骤。需要注意的是,使用Session来存储购物车信息需要考虑并发访问的情况,可以使用同步机制或者使用分布式Session来解决并发访问的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值