Skip to content

Commit b45afe7

Browse files
committed
Promotions UI: Make option value picker depend on product ID
When creating an option value condition, we only want to have option values that fit the product in question. This commit makes it such that the option value picker re-initializes when the selected product changes.
1 parent 8947ff5 commit b45afe7

File tree

4 files changed

+43
-49
lines changed

4 files changed

+43
-49
lines changed

promotions/app/javascript/backend/solidus_promotions/controllers/product_option_values_controller.js

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@ export default class extends Controller {
66
connect() {
77
this.wrapperClass =
88
this.data.get("wrapperClass") || "promo-condition-option-value";
9-
10-
this.element.querySelectorAll("." + this.wrapperClass).forEach((element) => this.buildSelects(element))
119
}
1210

1311
add_row(event) {
1412
event.preventDefault();
1513

1614
var content = this.templateTarget.innerHTML;
1715
this.linksTarget.insertAdjacentHTML("beforebegin", content);
18-
this.buildSelects(this.linksTarget.previousElementSibling)
1916
}
2017

2118
propagate_product_id_to_value_input(event) {
@@ -24,7 +21,9 @@ export default class extends Controller {
2421
// we first need to greedily match all other square brackets
2522
const regEx = /(\[.*\])\[.*?\]$/;
2623
let wrapper = event.target.closest("." + this.wrapperClass);
27-
let optionValuesInput = wrapper.querySelector(".option-values-select[type='hidden']");
24+
let optionValuesInput = wrapper.querySelector("[is=option-value-picker]");
25+
optionValuesInput.dataset.productId = event.target.value;
26+
optionValuesInput.value = "";
2827
optionValuesInput.name = optionValuesInput.name.replace(
2928
regEx,
3029
`$1[${event.target.value}]`
@@ -37,26 +36,4 @@ export default class extends Controller {
3736
let wrapper = event.target.closest("." + this.wrapperClass);
3837
wrapper.remove();
3938
}
40-
41-
// helper functions
42-
43-
buildSelects(wrapper) {
44-
let productSelect = wrapper.querySelector(".product-select")
45-
let optionValueSelect = wrapper.querySelector(".option-values-select[type='hidden']")
46-
this.buildProductSelect(productSelect)
47-
$(optionValueSelect).optionValueAutocomplete({ productSelect });
48-
}
49-
50-
buildProductSelect(productSelect) {
51-
var jQueryProductSelect = $(productSelect)
52-
jQueryProductSelect.productAutocomplete({
53-
multiple: false,
54-
})
55-
// capture the jQuery "change" event and re-emit it as DOM event "select2Change"
56-
// so that Stimulus can capture it
57-
jQueryProductSelect.on('change', function () {
58-
let event = new Event('select2Change', { bubbles: true }) // fire a native event
59-
productSelect.dispatchEvent(event);
60-
});
61-
}
6239
}
Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
$.fn.optionValueAutocomplete = function (options) {
2-
'use strict';
2+
"use strict";
33

44
// Default options
5-
options = options || {}
6-
var multiple = typeof(options['multiple']) !== 'undefined' ? options['multiple'] : true;
7-
var productSelect = options['productSelect'];
8-
5+
options = options || {};
6+
var multiple = typeof options["multiple"] !== "undefined" ? options["multiple"] : true;
97
function formatOptionValue(option_value) {
108
return Select2.util.escapeMarkup(option_value.name);
119
}
@@ -14,44 +12,58 @@ $.fn.optionValueAutocomplete = function (options) {
1412
minimumInputLength: 3,
1513
multiple: multiple,
1614
initSelection: function (element, callback) {
17-
$.get(Spree.pathFor('api/option_values'), {
18-
ids: element.val().split(','),
19-
token: Spree.api_key
20-
}, function (data) {
21-
callback(multiple ? data : data[0]);
22-
});
15+
$.get(
16+
Spree.pathFor("api/option_values"),
17+
{
18+
ids: element.val().split(","),
19+
token: Spree.api_key,
20+
},
21+
function (data) {
22+
callback(multiple ? data : data[0]);
23+
}
24+
);
2325
},
2426
ajax: {
25-
url: Spree.pathFor('api/option_values'),
26-
datatype: 'json',
27+
url: Spree.pathFor("api/option_values"),
28+
datatype: "json",
2729
data: function (term, page) {
28-
var productId = typeof(productSelect) !== 'undefined' ? $(productSelect).select2('val') : null;
30+
var productId = this[0].dataset.productId;
2931
return {
3032
q: {
3133
name_cont: term,
32-
variants_product_id_eq: productId
34+
variants_product_id_eq: productId,
3335
},
34-
token: Spree.api_key
36+
token: Spree.api_key,
3537
};
3638
},
3739
results: function (data, page) {
3840
return { results: data };
39-
}
41+
},
4042
},
4143
formatResult: formatOptionValue,
42-
formatSelection: formatOptionValue
44+
formatSelection: formatOptionValue,
4345
});
4446
};
4547

4648
class OptionValuePicker extends HTMLInputElement {
4749
connectedCallback() {
48-
const container = this.closest(".promo-condition-option-value");
49-
const productPicker = container.querySelector('input[is="product-picker"]');
50+
$(this).optionValueAutocomplete();
5051

51-
$(this).optionValueAutocomplete({
52-
productSelect: productPicker,
52+
this.observer = new MutationObserver((muts) => {
53+
for (const m of muts) {
54+
if (m.attributeName.startsWith("data-product-id")) {
55+
this.restart();
56+
}
57+
}
5358
});
59+
60+
this.observer.observe(this, { attributes: true });
61+
}
62+
63+
restart() {
64+
$(this).select2("destroy");
65+
$(this).optionValueAutocomplete();
5466
}
5567
}
5668

57-
customElements.define('option-value-picker', OptionValuePicker, { extends: 'input' });
69+
customElements.define("option-value-picker", OptionValuePicker, { extends: "input" });

promotions/app/javascript/backend/solidus_promotions/web_components/product_picker.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ class ProductPicker extends HTMLInputElement {
22
connectedCallback() {
33
const multiple = this.dataset.multiple !== "false";
44
$(this).productAutocomplete({ multiple });
5+
$(this).on("change", (_) => {
6+
let event = new Event('select2Change', { bubbles: true }) // fire a native event
7+
this.dispatchEvent(event)
8+
})
59
}
610
}
711

promotions/lib/views/backend/solidus_promotions/admin/condition_fields/line_item_option_value/_option_value_fields.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
class="fullwidth"
1616
name="<%= form.object_name %>[preferred_eligible_values][<%= product_option_values[0] %>]"
1717
type="hidden"
18+
data-product-id="<%= product_option_values[0] %>"
1819
value="<%= product_option_values[1].join(",") %>"
1920
>
2021
</div>

0 commit comments

Comments
 (0)