diff --git a/vendor/magento/module-bundle/ViewModel/ValidateQuantity.php b/vendor/magento/module-bundle/ViewModel/ValidateQuantity.php
new file mode 100644
index 000000000000..ee7e2064e906
--- /dev/null
+++ b/vendor/magento/module-bundle/ViewModel/ValidateQuantity.php
@@ -0,0 +1,43 @@
+serializer = $serializer;
+ }
+
+ /**
+ * Returns quantity validator.
+ *
+ * @return string
+ */
+ public function getQuantityValidators(): string
+ {
+ $validators['validate-item-quantity'] = [];
+
+ return $this->serializer->serialize($validators);
+ }
+}
diff --git a/vendor/magento/module-bundle/view/base/web/js/price-bundle.js b/vendor/magento/module-bundle/view/base/web/js/price-bundle.js
index 207a97c270ee..5b72327dc740 100644
--- a/vendor/magento/module-bundle/view/base/web/js/price-bundle.js
+++ b/vendor/magento/module-bundle/view/base/web/js/price-bundle.js
@@ -22,9 +22,9 @@ define([
priceBoxSelector: '.price-box',
optionHandlers: {},
optionTemplate: '<%- data.label %>' +
- '<% if (data.finalPrice.value) { %>' +
- ' +<%- data.finalPrice.formatted %>' +
- '<% } %>',
+ '<% if (data.finalPrice.value) { %>' +
+ ' +<%- data.finalPrice.formatted %>' +
+ '<% } %>',
controlContainer: 'dd', // should be eliminated
priceFormat: {},
isFixedPrice: false,
@@ -107,12 +107,15 @@ define([
changes = defaultGetOptionValue(bundleOption, this.options.optionConfig);//eslint-disable-line
}
- if (changes) {
- priceBox.trigger('updatePrice', changes);
- }
+ // eslint-disable-next-line no-use-before-define
+ if (isValidQty(bundleOption)) {
+ if (changes) {
+ priceBox.trigger('updatePrice', changes);
+ }
- this._displayTierPriceBlock(bundleOption);
- this.updateProductSummary();
+ this._displayTierPriceBlock(bundleOption);
+ this.updateProductSummary();
+ }
},
/**
@@ -132,7 +135,10 @@ define([
.selections[field.data('optionValueId')];
optionConfig.qty = field.val();
- optionInstance.trigger('change');
+ // eslint-disable-next-line no-use-before-define
+ if (isValidQty(optionInstance)) {
+ optionInstance.trigger('change');
+ }
}
},
@@ -373,6 +379,23 @@ define([
return changes;
}
+ /**
+ * Check the quantity field if negative value occurs.
+ *
+ * @param {Object} bundleOption
+ */
+ function isValidQty(bundleOption) {
+ var isValid = true,
+ qtyElem = bundleOption.data('qtyField'),
+ bundleOptionType = bundleOption.prop('type');
+
+ if (['radio', 'select-one'].includes(bundleOptionType) && qtyElem.val() < 0) {
+ isValid = false;
+ }
+
+ return isValid;
+ }
+
/**
* Helper to toggle qty field
* @param {jQuery} element
diff --git a/vendor/magento/module-bundle/view/frontend/layout/catalog_product_view_type_bundle.xml b/vendor/magento/module-bundle/view/frontend/layout/catalog_product_view_type_bundle.xml
index d12f2e8f6a95..d816abfa9d10 100644
--- a/vendor/magento/module-bundle/view/frontend/layout/catalog_product_view_type_bundle.xml
+++ b/vendor/magento/module-bundle/view/frontend/layout/catalog_product_view_type_bundle.xml
@@ -32,12 +32,14 @@
\Magento\Bundle\Block\DataProviders\OptionPriceRenderer
+ Magento\Bundle\ViewModel\ValidateQuantity
\Magento\Bundle\Block\DataProviders\OptionPriceRenderer
+ Magento\Bundle\ViewModel\ValidateQuantity
@@ -49,7 +51,7 @@
-
+
diff --git a/vendor/magento/module-bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml b/vendor/magento/module-bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml
index 11ed226c176c..706b28049470 100644
--- a/vendor/magento/module-bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml
+++ b/vendor/magento/module-bundle/view/frontend/templates/catalog/product/view/type/bundle/option/radio.phtml
@@ -3,13 +3,17 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+use Magento\Bundle\ViewModel\ValidateQuantity;
?>
getOption(); ?>
getSelections(); ?>
getDefaultSelection(); ?>
getDefaultValues(); ?>
-
+getData('validateQuantityViewModel');
+?>