diff --git a/app/webpacker/controllers/bulk_form_controller.js b/app/webpacker/controllers/bulk_form_controller.js index 0af566b271..bd1ab3b854 100644 --- a/app/webpacker/controllers/bulk_form_controller.js +++ b/app/webpacker/controllers/bulk_form_controller.js @@ -63,7 +63,7 @@ export default class BulkFormController extends Controller { // For each record, check if any fields are changed // TODO: optimise basd on current state. if field is changed, but form already changed, no need to update (and vice versa) const changedRecordCount = Object.values(this.recordElements).filter((elements) => - elements.some(this.#isChanged), + elements.some(this.#checkIsChanged.bind(this)), ).length; this.formChanged = changedRecordCount > 0 || this.errorValue; @@ -131,11 +131,17 @@ export default class BulkFormController extends Controller { }); } - #isChanged(element) { - if(!element.isConnected) { - return false; + // Check if changed, and mark with class if it is. + #checkIsChanged(element) { + if(!element.isConnected) return false; - } else if (element.type == "checkbox") { + const changed = this.#isChanged(element); + element.classList.toggle("changed", changed); + return changed; + } + + #isChanged(element) { + if (element.type == "checkbox") { return element.defaultChecked !== undefined && element.checked != element.defaultChecked; } else if (element.type == "select-one") { diff --git a/spec/javascripts/stimulus/bulk_form_controller_test.js b/spec/javascripts/stimulus/bulk_form_controller_test.js index 82d83c7271..2f1e8ea429 100644 --- a/spec/javascripts/stimulus/bulk_form_controller_test.js +++ b/spec/javascripts/stimulus/bulk_form_controller_test.js @@ -99,6 +99,59 @@ describe("BulkFormController", () => { expect(input1b.classList).not.toContain('changed'); expect(input2.classList).toContain('changed'); }); + + describe("select not include_blank", () => { + beforeEach(() => { + document.body.innerHTML = ` +
+
+ +
+ +
+ `; + }); + + it("shows as changed", () => { + // Expect select to show changed (select-one always has something selected) + expect(select1.classList).toContain('changed'); + + // Change selection + select1.options[0].selected = false; + select1.options[1].selected = true; + select1.dispatchEvent(new Event("input")); + expect(select1.classList).toContain('changed'); + }); + }); + + describe("select-one with include_blank", () => { + beforeEach(() => { + document.body.innerHTML = ` +
+
+ +
+ +
+ `; + }); + + it("does not show as changed", () => { + expect(select1.classList).not.toContain('changed'); + + // Change selection + select1.options[0].selected = false; + select1.options[1].selected = true; + select1.dispatchEvent(new Event("input")); + expect(select1.classList).toContain('changed'); + }); + }); }) describe("activating sections, and showing a summary", () => {