[IMP] web: multi record selector: add keyboard navigation

This commit adds keyboard navigation to the multi record selector.

Part of task-id 3433922

Part-of: odoo/odoo#138464
This commit is contained in:
Pierre Rousseau
2023-10-13 11:46:21 +00:00
parent d949e001c9
commit 29e301fe32
3 changed files with 68 additions and 6 deletions
@@ -5,6 +5,7 @@ import { TagsList } from "@web/core/tags_list/tags_list";
import { useService } from "@web/core/utils/hooks";
import { RecordAutocomplete } from "./record_autocomplete";
import { _t } from "@web/core/l10n/translation";
import { useTagNavigation } from "./tag_navigation_hook";
export class MultiRecordSelector extends Component {
static props = {
@@ -21,6 +22,7 @@ export class MultiRecordSelector extends Component {
setup() {
this.nameService = useService("name");
this.onTagKeydown = useTagNavigation("multiRecordSelector", this.deleteTag.bind(this));
onWillStart(() => this.computeDerivedParams());
onWillUpdateProps((nextProps) => this.computeDerivedParams(nextProps));
}
@@ -57,15 +59,20 @@ export class MultiRecordSelector extends Component {
return {
text,
onDelete: () => {
this.props.update([
...this.props.resIds.slice(0, index),
...this.props.resIds.slice(index + 1),
]);
this.deleteTag(index);
},
onKeydown: this.onTagKeydown,
};
});
}
deleteTag(index) {
this.props.update([
...this.props.resIds.slice(0, index),
...this.props.resIds.slice(index + 1),
]);
}
update(resIds) {
this.props.update([...this.props.resIds, ...resIds]);
}
@@ -2,7 +2,7 @@
<templates xml:space="preserve">
<t t-name="web.MultiRecordSelector" >
<div class="o_input d-flex flex-wrap gap-1 o_multi_record_selector">
<div class="o_input d-flex flex-wrap gap-1 o_multi_record_selector" t-ref="multiRecordSelector">
<TagsList tags="tags"/>
<RecordAutocomplete
resModel="props.resModel"
@@ -2,7 +2,7 @@
import { MultiRecordSelector } from "@web/core/record_selectors/multi_record_selector";
import { makeTestEnv } from "../../helpers/mock_env";
import { getFixture, mount, click } from "../../helpers/utils";
import { getFixture, mount, click, triggerEvent, editInput } from "../../helpers/utils";
import { registry } from "@web/core/registry";
import { hotkeyService } from "@web/core/hotkeys/hotkey_service";
@@ -187,4 +187,59 @@ QUnit.module("Web Components", (hooks) => {
const input = target.querySelector(".o_multi_record_selector input");
assert.strictEqual(input.placeholder, "");
});
QUnit.test("Can delete a tag with Backspace", async (assert) => {
await makeMultiRecordSelector({
resModel: "partner",
resIds: [1, 2],
});
await triggerEvent(target, ".o-autocomplete input", "keydown", { key: "Backspace" });
assert.strictEqual(target.querySelectorAll(".o_tag").length, 1);
assert.strictEqual(target.querySelector(".o_tag").textContent, "Alice");
});
QUnit.test("Can focus tags with arrow right and left", async (assert) => {
await makeMultiRecordSelector({
resModel: "partner",
resIds: [1, 2],
});
target.querySelector(".o-autocomplete input").focus();
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowleft" });
assert.strictEqual(document.activeElement.textContent, "Bob");
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowleft" });
assert.strictEqual(document.activeElement.textContent, "Alice");
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowleft" });
assert.hasClass(document.activeElement, "o-autocomplete--input");
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowright" });
assert.strictEqual(document.activeElement.textContent, "Alice");
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowright" });
assert.strictEqual(document.activeElement.textContent, "Bob");
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowright" });
assert.hasClass(document.activeElement, "o-autocomplete--input");
});
QUnit.test("Delete the focused element", async (assert) => {
await makeMultiRecordSelector({
resModel: "partner",
resIds: [1, 2],
});
target.querySelector(".o-autocomplete input").focus();
await triggerEvent(document.activeElement, "", "keydown", { key: "arrowright" });
assert.strictEqual(document.activeElement.textContent, "Alice");
await triggerEvent(document.activeElement, "", "keydown", { key: "Backspace" });
assert.strictEqual(target.querySelectorAll(".o_tag").length, 1);
assert.strictEqual(target.querySelector(".o_tag").textContent, "Bob");
});
QUnit.test("Backspace do nothing when the input is currently edited", async (assert) => {
await makeMultiRecordSelector({
resModel: "partner",
resIds: [1, 2],
});
target.querySelector(".o-autocomplete input").focus();
await editInput(target, ".o-autocomplete input", "a");
assert.strictEqual(document.activeElement.value, "a");
await triggerEvent(document.activeElement, "", "keydown", { key: "Backspace" });
assert.strictEqual(target.querySelectorAll(".o_tag").length, 2);
});
});