Skip to content

Commit aa85178

Browse files
committed
refactor: add alchemy-picture-description-select component
Instead of an inline script tag we use a custom element that handles the internal event handling much more reliable. Signed-off-by: Thomas von Deyen <vondeyen@blish.cloud>
1 parent bf064ef commit aa85178

File tree

6 files changed

+70
-22
lines changed

6 files changed

+70
-22
lines changed

app/components/alchemy/admin/picture_description_select.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ module Alchemy
22
module Admin
33
class PictureDescriptionSelect < ViewComponent::Base
44
erb_template <<-ERB
5-
<label class="inline-label">
6-
<%= label %>
7-
<%= select name_prefix, :language_id,
8-
options_for_select(language_options, selected:), {},
9-
id: "picture_description_select",
10-
data: {url:} %>
11-
</label>
5+
<alchemy-picture-description-select url="<%= url %>">
6+
<label class="inline-label">
7+
<%= label %>
8+
<%= select name_prefix, :language_id,
9+
options_for_select(language_options, selected:) %>
10+
</label>
11+
</alchemy-picture-description-select>
1212
ERB
1313

1414
def initialize(url:, selected:, name_prefix:)

app/javascript/alchemy_admin/components/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import "alchemy_admin/components/uploader"
2525
import "alchemy_admin/components/overlay"
2626
import "alchemy_admin/components/page_publication_fields"
2727
import "alchemy_admin/components/page_select"
28+
import "alchemy_admin/components/picture_description_select"
2829
import "alchemy_admin/components/picture_thumbnail"
2930
import "alchemy_admin/components/preview_window"
3031
import "alchemy_admin/components/select"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class PictureDescriptionSelect extends HTMLElement {
2+
constructor() {
3+
super()
4+
this.addEventListener("change", this)
5+
}
6+
7+
handleEvent(event) {
8+
switch (event.type) {
9+
case "change":
10+
this.onChange()
11+
break
12+
}
13+
}
14+
15+
onChange() {
16+
const url = new URL(this.getAttribute("url"))
17+
const select = this.querySelector("select")
18+
url.searchParams.set("language_id", select.value)
19+
Turbo.visit(url, { frame: "picture_descriptions" })
20+
}
21+
}
22+
23+
customElements.define(
24+
"alchemy-picture-description-select",
25+
PictureDescriptionSelect
26+
)

app/views/alchemy/admin/pictures/_picture_description_field.html.erb

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,3 @@
1414
picture_description: @picture_description %>
1515
</turbo-frame>
1616
</div>
17-
18-
<script>
19-
(function ($) {
20-
const select = $.getElementById("picture_description_select")
21-
22-
if (select) {
23-
select.addEventListener("change", () => {
24-
const url = new URL(select.dataset.url)
25-
url.searchParams.set("language_id", select.value)
26-
Turbo.visit(url, { frame: "picture_descriptions" })
27-
})
28-
}
29-
})(document)
30-
</script>

spec/components/alchemy/admin/picture_description_select_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
it "renders the select box with both languages" do
3030
expect(page).to have_select("Language", options: ["EN", "DE"], selected: "EN")
31-
expect(page).to have_selector("select[data-url='/some/url']")
31+
expect(page).to have_selector("alchemy-picture-description-select[url='/some/url']")
3232
end
3333
end
3434
end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { vi } from "vitest"
2+
import { renderComponent } from "./component.helper"
3+
import "alchemy_admin/components/picture_description_select"
4+
5+
describe("alchemy-picture-description-select", () => {
6+
/**
7+
*
8+
* @type {HTMLElement | undefined}
9+
*/
10+
let component = undefined
11+
12+
beforeEach(() => {
13+
const html = `
14+
<alchemy-picture-description-select url="http://example.com/some/url">
15+
<select>
16+
<option value="1"></option>
17+
<option value="2" selected></option>
18+
</select>
19+
</alchemy-picture-description-select>
20+
`
21+
component = renderComponent("alchemy-picture-description-select", html)
22+
global.Turbo = { visit: vi.fn() }
23+
})
24+
25+
it("should use Turbo to reload the picture_descriptions frame", () => {
26+
const select = component.querySelector("select")
27+
const event = new Event("change", { bubbles: true })
28+
select.dispatchEvent(event)
29+
30+
expect(Turbo.visit).toHaveBeenCalledWith(
31+
new URL("http://example.com/some/url?language_id=2"),
32+
{ frame: "picture_descriptions" }
33+
)
34+
})
35+
})

0 commit comments

Comments
 (0)