diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index c849c072bb..750746ddc3 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -61,12 +61,12 @@ - product.variants.each_with_index do |variant, variant_index| = form.fields_for("products][#{product_index}][variants_attributes][", variant, index: variant_index) do |variant_form| - %tr.condensed + %tr.condensed{ 'data-controller': "variant" } = render partial: 'variant_row', locals: { variant:, f: variant_form } = form.fields_for("products][#{product_index}][variants_attributes][NEW_RECORD", product.variants.build) do |new_variant_form| %template{ 'data-nested-form-target': "template" } - %tr.condensed + %tr.condensed{ 'data-controller': "variant" } = render partial: 'variant_row', locals: { variant: new_variant_form.object, f: new_variant_form } %tr{ 'data-nested-form-target': "target" } diff --git a/app/webpacker/controllers/product_controller.js b/app/webpacker/controllers/product_controller.js index cb66b34d65..942f3b02e1 100644 --- a/app/webpacker/controllers/product_controller.js +++ b/app/webpacker/controllers/product_controller.js @@ -32,5 +32,7 @@ export default class ProductController extends Controller { this.variantUnit.value = variant_unit_with_scale; this.variantUnitScale.value = ""; } + this.variantUnit.dispatchEvent(new Event("change")); + this.variantUnitScale.dispatchEvent(new Event("change")); } } diff --git a/app/webpacker/controllers/variant_controller.js b/app/webpacker/controllers/variant_controller.js new file mode 100644 index 0000000000..f532009d8b --- /dev/null +++ b/app/webpacker/controllers/variant_controller.js @@ -0,0 +1,63 @@ +import { Controller } from "stimulus"; + +// Dynamically update related variant fields +// +export default class VariantController extends Controller { + connect() { + // Assuming these will be available on the variant soon, just a quick hack to find the product fields: + const product = this.element.closest("[data-record-id]"); + this.variantUnit = product.querySelector('[name$="[variant_unit]"]'); + this.variantUnitScale = product.querySelector('[name$="[variant_unit_scale]"]'); + this.variantUnitName = product.querySelector('[name$="[variant_unit_name]"]'); + + this.unitValueWithDescription = this.element.querySelector( + '[name$="[unit_value_with_description]"]', + ); + this.displayAs = this.element.querySelector('[name$="[display_as]"]'); + this.unitToDisplay = this.element.querySelector('[name$="[unit_to_display]"]'); + + // on unit changed; update display_as:placeholder and unit_to_display + [this.variantUnit, this.variantUnitScale, this.variantUnitName].forEach((element) => { + element.addEventListener("change", this.#unitChanged.bind(this), { passive: true }); + }); + + // on unit_value_with_description changed; update unit_value and unit_description + // on unit_value and/or unit_description changed; update display_as:placeholder and unit_to_display + this.unitValueWithDescription.addEventListener("input", this.#unitValueChanged.bind(this), { + passive: true, + }); + + // on display_as changed; update unit_to_display (how does this relate to unit_presentation?) + this.displayAs.addEventListener("input", this.#updateUnitDisplay.bind(this), { passive: true }); + } + + disconnect() { + // Make sure to clean up anything that happened outside + } + + // private + + // Extract variant_unit and variant_unit_scale from dropdown variant_unit_with_scale, + // and update hidden product fields + #unitChanged(event) { + //todo: deduplicate events. + //Hmm in hindsight the logic in product_controller should be inn this controller already. then we can do everything in one event, and store the generated name in an instance variable. + this.#updateUnitDisplay(); + } + + // Extract unit_value and unit_description from unit_value_with_description, + // and update hidden fields + #unitValueChanged(event) { + //todo: deduplicate events. + this.#updateUnitDisplay(); + } + + // Update display_as placeholder and unit_to_display + #updateUnitDisplay() { + // const unitDisplay = OptionValueNamer... + const unitDisplay = + this.unitValueWithDescription.value + " " + (this.variantUnitName.value || "~g"); //To Remove: DEMO only + this.displayAs.placeholder = unitDisplay; + this.unitToDisplay.textContent = this.displayAs.value || unitDisplay; + } +}