mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-13 23:37:47 +00:00
Mark tom-select as changed
Thankfully I was able to use basic DOM features, so there's no coupling of the logic with tom-select. It wasn't going to be simple to get tom-select to listen for the 'changed' class on the original select, so I found a simple solution with a CSS sibling selector instead.
This commit is contained in:
@@ -1,6 +1,19 @@
|
||||
import { Controller } from "stimulus";
|
||||
|
||||
// Manages "changed" state for a form with multiple records
|
||||
// Manage "changed" state for a form with multiple records
|
||||
//
|
||||
// When any elements are changed:
|
||||
// - the element is marked ".changed"
|
||||
// - "actions" element appears
|
||||
// - "changedSummary" element is updated using I18n
|
||||
// - "disableSelector" elements are disabled
|
||||
// - The browser will warn if trying to leave the page
|
||||
//
|
||||
// Supported element types:
|
||||
// - input[type=text] and similar
|
||||
// - input[type=checkbox]
|
||||
// - select (single) - including tom-select
|
||||
//
|
||||
export default class BulkFormController extends Controller {
|
||||
static targets = ["actions", "changedSummary"];
|
||||
static values = {
|
||||
@@ -113,6 +126,11 @@ export default class BulkFormController extends Controller {
|
||||
#isChanged(element) {
|
||||
if (element.type == "checkbox") {
|
||||
return element.defaultChecked !== undefined && element.checked != element.defaultChecked;
|
||||
|
||||
} else if (element.type == "select-one") {
|
||||
const defaultSelected = Array.from(element.options).find((opt)=>opt.hasAttribute('selected'));
|
||||
return element.selectedOptions[0] != defaultSelected;
|
||||
|
||||
} else {
|
||||
return element.defaultValue !== undefined && element.value != element.defaultValue;
|
||||
}
|
||||
|
||||
@@ -188,3 +188,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display as "changed" if sibling select is marked as changed.
|
||||
select.changed + .ts-wrapper {
|
||||
&.single, &.multi {
|
||||
.ts-control {
|
||||
border-color: $color-txt-changed-brd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ describe("BulkFormController", () => {
|
||||
<div data-record-id="1">
|
||||
<input id="input1a" type="text" value="initial1a">
|
||||
<input id="input1b" type="text" value="initial1b">
|
||||
<select id="select1">
|
||||
<option>one</option>
|
||||
<option selected>two</option>
|
||||
</select>
|
||||
<button>a button is counted as a form element, but value is undefined</button>
|
||||
</div>
|
||||
<div data-record-id="2">
|
||||
@@ -47,7 +51,7 @@ describe("BulkFormController", () => {
|
||||
});
|
||||
|
||||
describe("marking changed fields", () => {
|
||||
it("onInput", () => {
|
||||
it("input: onInput", () => {
|
||||
input1a.value = 'updated1a';
|
||||
input1a.dispatchEvent(new Event("input"));
|
||||
// Expect only first field to show changed
|
||||
@@ -59,7 +63,23 @@ describe("BulkFormController", () => {
|
||||
input1a.value = 'initial1a';
|
||||
input1a.dispatchEvent(new Event("input"));
|
||||
expect(input1a.classList).not.toContain('changed');
|
||||
});
|
||||
|
||||
it("select: onInput", () => {
|
||||
// Select a different option (it's the only way in Jest..)
|
||||
select1.options[0].selected = true;
|
||||
select1.options[1].selected = false;
|
||||
select1.dispatchEvent(new Event("input"));
|
||||
// Expect select to show changed
|
||||
expect(input1a.classList).not.toContain('changed');
|
||||
expect(input1b.classList).not.toContain('changed');
|
||||
expect(select1.classList).toContain('changed');
|
||||
|
||||
// Change back to original value
|
||||
select1.options[0].selected = false;
|
||||
select1.options[1].selected = true;
|
||||
select1.dispatchEvent(new Event("input"));
|
||||
expect(select1.classList).not.toContain('changed');
|
||||
});
|
||||
|
||||
it("multiple fields", () => {
|
||||
|
||||
Reference in New Issue
Block a user