diff --git a/app/components/tag_list_input_component/tag_list_input_component.html.haml b/app/components/tag_list_input_component/tag_list_input_component.html.haml index 8be197702d..0149584b2c 100644 --- a/app/components/tag_list_input_component/tag_list_input_component.html.haml +++ b/app/components/tag_list_input_component/tag_list_input_component.html.haml @@ -1,11 +1,19 @@ -= f.hidden_field method.to_sym, value: tags.join(",") -.tags-input - .tags - %ul.tag-list - - tags.each do |tag| - %li.tag-item - .tag-template - %span=tag - %a.remove-button - ✖ - = text_field_tag :variant_add_tag, nil, class: "input", placeholder: placeholder +- #%div{ "data-controller": "tag-list-input-component--tag-list-input" } +%div{ "data-controller": "tag-list-input-component--tag-list-input" } + = f.hidden_field method.to_sym, value: tags.join(","), "data-tag-list-input-component--tag-list-input-target": "tagList" + .tags-input{ } + .tags + %ul.tag-list{"data-tag-list-input-component--tag-list-input-target": "list"} + %template{"data-tag-list-input-component--tag-list-input-target": "template"} + %li.tag-item + .tag-template + %span + %a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" } + ✖ + - tags.each do |tag| + %li.tag-item + .tag-template + %span=tag + %a.remove-button{ "data-action": "click->tag-list-input-component--tag-list-input#removeTag" } + ✖ + = text_field_tag "variant_add_tag_#{f.object.id}".to_sym, nil, class: "input", placeholder: placeholder, "data-action": "keydown.enter->tag-list-input-component--tag-list-input#addTag keyup->tag-list-input-component--tag-list-input#filterInput", "data-tag-list-input-component--tag-list-input-target": "newTag" diff --git a/app/components/tag_list_input_component/tag_list_input_component.scss b/app/components/tag_list_input_component/tag_list_input_component.scss index 751a2a4820..64e7998d29 100644 --- a/app/components/tag_list_input_component/tag_list_input_component.scss +++ b/app/components/tag_list_input_component/tag_list_input_component.scss @@ -33,7 +33,6 @@ Helvetica, Arial, sans-serif; - font-size: 85%; height: 25px; line-height: 25px; border: none; diff --git a/app/components/tag_list_input_component/tag_list_input_controller.js b/app/components/tag_list_input_component/tag_list_input_controller.js new file mode 100644 index 0000000000..1316b85855 --- /dev/null +++ b/app/components/tag_list_input_component/tag_list_input_controller.js @@ -0,0 +1,40 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["tagList", "newTag", "template", "list"]; + + addTag() { + // add to tagList + this.tagListTarget.value = this.tagListTarget.value.concat(`,${this.newTagTarget.value}`); + + // Create new li component with value + const newTagElement = this.templateTarget.content.cloneNode(true); + const spanElement = newTagElement.querySelector("span"); + spanElement.innerText = this.newTagTarget.value; + this.listTarget.appendChild(newTagElement); + + // Clear new tag value + this.newTagTarget.value = ""; + } + + removeTag(event) { + // Text to remove + const tagName = event.srcElement.previousElementSibling.textContent; + + // Remove tag from list + const tags = this.tagListTarget.value.split(","); + const index = tags.indexOf(tagName); + tags.splice(index, 1); + this.tagListTarget.value = tags.join(","); + + // Remove HTML element from the list + event.srcElement.parentElement.parentElement.remove(); + } + + // Strip comma from tag name + filterInput(event) { + if (event.key === ",") { + event.srcElement.value = event.srcElement.value.replace(",",""); + } + } +} diff --git a/spec/javascripts/stimulus/tag_list_input_controller_test.js b/spec/javascripts/stimulus/tag_list_input_controller_test.js new file mode 100644 index 0000000000..b9c266de1d --- /dev/null +++ b/spec/javascripts/stimulus/tag_list_input_controller_test.js @@ -0,0 +1,126 @@ +/** + * @jest-environment jsdom + */ + +import { Application } from "stimulus"; +import tag_list_input_controller from "../../../app/components/tag_list_input_component/tag_list_input_controller"; + +describe("TagListInputController", () => { + beforeAll(() => { + const application = Application.start(); + application.register("tag-list-input-component--tag-list-input", tag_list_input_controller); + }); + + beforeEach(() => { + document.body.innerHTML = ` +